Browse DevX
Sign up for e-mail newsletters from DevX


Use the Template Design Pattern to Customize a Base Class Service in a Derived Class-3 : Page 3




Building the Right Environment to Support AI, Machine Learning and Deep Learning

In essence, the Template design pattern separates between mandatory primitive operations (which are implemented in the base class) and hooks for customized operations that a subclass may redefine later. Following these guidelines, the modified Viewer class now looks like this:

class Viewer { public: int Open(const char * filename) { init();//mandatory steps: CRC check, authorization if (is_custimized() ) customized_init();//allow customization by subclasses } virtual ~Viewer(); protected: //hooks for a subclass's customizations virtual bool is_custimized()=0; virtual void customized_init() {} private: //mandatory primitive operations void init(); };

When a subclass overrides a protected member function, it changes that function's access to private:

class MyViewer: public Viewer { //.. private: bool is_custimized() const; void customized_init(); }

The Well-Tempered Template
How does it work? A subclass that wishes to retain the base class' functionality as-is shall provide a trivial implementation of is_customized():

bool is_customized() const {return false;)

When a subclass object calls Open(), it always executes Viewer::Open() because this function isn't virtual. Open() in turn invokes init() to perform the mandatory primitive operations and then calls the subclass' is_customized(). A subclass that wishes to customize the behavior of Open() must change the return value of is_customized() to true and override customized_init() as necessary.

A Template Recipe
Let's summarize the design principles of a Template function:

  • A Template function is a nonvirtual public member function that performs a series of primitive operations.
  • Some of the primitive operations are mandatory; others may be customizable.
  • Mandatory operations are nonvirtual private members of the base class.
  • Customized primitive operations are declared virtual protected in the base class, but change their access to private in a subclass.
  • Customizable primitive operations that must be overridden are declared pure virtual in the base class; those that may be overridden are declared virtual.
In addition to the obvious benefit of providing a skeletal implementation in the base class while allowing a subclass to redefine certain portions thereof, the Template design pattern minimizes the number of primitive operations that a derived class must perform to flesh out the Template function. In this example, a derived class merely provides a trivial definition of is_customizable() to retain the base class functionality.

Danny Kalev is a certified system analyst and software engineer specializing in C++. He was a member of the C++ standards committee between 1997 and 2000 and has since been involved informally in the C++0x standardization process. He is the author of "The ANSI/ISO Professional C++ Programmer's Handbook" and "The Informit C++ Reference Guide: Techniques, Insight, and Practical Advice on C++."
Thanks for your registration, follow us on our social networks to keep up-to-date