Non-virtual interface idiom (NVI)

In almost every cases, it’s recommended to follow OOAD principles, but sometimes we should try to look some other alternatives, provided by programming languages, which could be a better options for certain situations.


In C++, we can implement virtual function in private and we can redefine its behavior in derived class's private and it will work in same way(did you try that?).

When we define virtual function as private and expose a non-virtual public function to outer world, we call it “non-virtual interface idiom”. Non-virtual public function will internally call virtual function, in other words you are not exposing your virtual function to client.

You will achieve high encapsulation, plus we can add pre and post execution/condition in the body of non-virtual public function. Call some set of functions, as prerequisite of calling virtual function, and after call returns from virtual function, again call some set of function as part of post cleanups/conditions, according to your need. 


C++ implementation of NVI -

  /**************************************************************************************
 /* The template method pattern via the non-Virtual interface idiom.
 /* or say -> non-virtual interface idiom (NVI)
 ***************************************************************************************/
 
 //*************************************************************************************
 // Header files
 #include<iostream>
 using namespace std;
 
 //*************************************************************************************
 //Global variables and functions 
 
 //*************************************************************************************
 // Class
 class GameCharacter {
  public:
  int HealthValue() const;
  private:
  virtual int DoHealthValue() const;
 };
 ///////////////////////////////////////////////////////////////////////////////////////
 int GameCharacter::HealthValue() const {
  cout<<"inside GameCharacter::HealthValue "<<endl;
  return DoHealthValue();
 }
 ///////////////////////////////////////////////////////////////////////////////////////
 int GameCharacter::DoHealthValue() const {
  cout<<"inside GameCharacter::DoHealthValue "<<endl;
  return 7; // temp implementation
 }
 //*************************************************************************************
 // Main functions 
 int main(int argc, char** argv) {
  GameCharacter objGameCharacter;
  cout<<"HealthValue for objGameCharacter - "<<objGameCharacter.HealthValue();
  return 0;
 }
 
 
  ///////////////////////////////////////////////////////////////////-------------OutPut
 /*
$ ./a.exe
inside GameCharacter::HealthValue
inside GameCharacter::DoHealthValue
HealthValue for objGameCharacter - 7

 */

C++  demonstration of private virtual function implementation in derived class -

 


 /**************************************************************************************
 /* Implementing private virtual functions
 /*
 /* (c) 2015 Kunjesh Singh Baghel, All Rights Reserved.
 /* https://sites.google.com/site/kunjeshsinghbaghel/
 ***************************************************************************************/
 
 //*************************************************************************************
 // Header files
 #include<iostream>
 using namespace std;
 //*************************************************************************************
 //Global variables and functions 
 
 //*************************************************************************************
 // Class
 class Base {
  public:
  void Display() const;
  
  private:
  virtual void ImpDisplay() const;
 };
 ///////////////////////////////////////////////////////////////////////////////////////
 void Base::Display() const {
  cout<<"inside Base::Display "<<endl;
  ImpDisplay();
 }
 ///////////////////////////////////////////////////////////////////////////////////////
 void Base::ImpDisplay() const {
  cout<<"inside Base::ImpDisplay "<<endl;
  
 }
 ///////////////////////////////////////////////////////////////////////////////////////
 class Derived : public Base {
  public:
   using Base::Display;
  private:
  virtual void ImpDisplay() const;
 };
 ///////////////////////////////////////////////////////////////////////////////////////
 void Derived::ImpDisplay() const {
  cout<<"inside Derived::ImpDisplay "<<endl;
 }
 //*************************************************************************************
 // Main functions 
 int main(int argc, char** argv) {
  Base *pointerBase;
  Base objBase;
  Derived objDerived;
  
  pointerBase = &objBase;
  pointerBase->Display();
  
  pointerBase = &objDerived;
  pointerBase->Display();

  return 0;
 }

 
 ///////////////////////////////////////////////////////////////////-------------OutPut
 /*
$ ./a.exe
inside Base::Display
inside Base::ImpDisplay
inside Base::Display
inside Derived::ImpDisplay
*/

Thanks for reading it. To read more on design patterns and basic design principles please see my web page. You can also join me on FB or on G++. Please drop comments for any question related to this blog.

Comments

Popular posts from this blog

Architectural patterns => Mud to structure => layers.

Architectural style -> Adoptable system -> Reflection.