200 likes | 326 Views
C++ Certificate Program C++ Intermediate. Template Method Pattern. Template Method Pattern. Design pattern, presents an algorithm skeleton in an operation, deferring some steps to client derived classes
E N D
C++ Certificate ProgramC++ Intermediate Template Method Pattern
Template Method Pattern • Design pattern, presents an algorithm skeleton in an operation, deferring some steps to client derived classes • Derived classes redefine certain steps of an algorithm without changing algorithm structure • Abstract class, contains only part of the logic needed to accomplish purpose
Enforces Invariance on Derived Classes • Algorithm itself is not mutable • Only very specific details left to derived classes • Excellent fit where the algorithm can be generalized enough to specify logic to be implemented by derived classes
Template Method Description • Template method is concrete method that calls one or more abstract methods where the missing logic would have appeared • Missing logic is provided by overriding abstract methods with implementations in the derived classes • Template method itself usually non-virtual
Factor Common Behaviors • Idea is to factor out common behavior among derived classes, keep it in base class • Specific, customized behaviors are deferred to the derived classes
Example class MyBase { public : MyBase(); // next two fcts provide default implementations virtual void operation1() { … } virtual void operation2() { … } // next fct must be implemented in subclasses virtual void operation2() = 0; void templateMethod() { operation1(); // some other (invariant) logic here operation2(); // more logic … operation3(); } };
Derived Class 1 class Derived1 : public MyBase { public : Derived1() : MyBase() {} virtual void derived1SpecificBehavior() {…} // now override behavior for operation1 virtual void operation1() { … } // use default implementation for operation2 // provide implementation for operation 3 virtual void operation3() { specificBehavior(); // … } };
Derived Class 2 class Derived2 : public MyBase { public : Derived2() : MyBase() {} // accept default behavior for operation 1 //override behavior for operation2 virtual void operation2() { … } // provide implementation for operation 3 virtual void operation3() { // … } };
Fundamentally Powerful • Note that template method algorithm specialized by implementation mix of operation1(), operation2(), and operation3() provided by Derived1 and Derived2 • This type of deferred behavior specialization is very powerful
Details • Template method algorithm owned and operated by parent (base) class, not overridden by the derived classes; sub-operations are virtual methods implemented in the derived classes • Note that parent class calls the operations of the derived classes, not other way round; parent class imposes algorithm invariance on derived classes
Step Definition • Virtual methods implemented by derived classes may be considered algorithm steps • Step’s implementation can vary depending on derived classes; may have default implementations • Some steps may be called “hooks”, generally have no default implementation, optionally overridden; may be considered placeholders for optional or future functionality
More Step Definition • Some steps may be implemented in abstract methods in the parent class • Basically steps are primitive operations, some must be overridden and some not
Inheritance vs Composition • In Template Method pattern, specialization through inheritance implements the delegated responsibilities • In general, the inheritance could be replaced by composition: Give MyBase class a pointer to a class implementing required functionality
MyBase Revisited class MyBase { public : MyBase(Substitute *s) : mSubstitute(s) {} void templateMethod() { mSubstitute->operation1(); // some other logic here mSubstitute->operation2(); // more logic … mSubstitute->operation3(); } private: Substitute* mSubstitute; };
Consequences • No longer a true Template Method pattern • Loses benefits of optional overriding - much more difficult to provide default implementations of operation[1..4] • Loses the power of inheritance
Private Inheritance vs Composition Revisited • Why use private inheritance instead of composition? • In both cases, hiding the interface of the base or composition class is accomplished • If inheritance capabilities needed, such as overriding virtual methods, choose private inheritance
Example • Need: functionality of Derived1 in new class named MyNewClass • Need: Derived1 interface not visible (not wanted, only implementation functionality is desired), so good candidate for composition • However, Derived1::operation1() presents specific behavior that may not be desired / appropriate; with inheritance, method can be overriden
Example class MyNewClass : private Derived1 { MyNewClass() : Derived1() {} virtual void derived1SpecificBehavior() { // override inappropriate behavior here } void someFunc() { templateMethod(); } };
Example Results • When someFunc() calls templateMethod(), Derived1::operation3() is called • Normally results in call to Derived1::derived1SpecificBehavior(), but now uses MyNewClass version to override • Same would not be true for composition (why?)
Summary • In general, private inheritance can always be replaced by composition. However, if the power of inheritance is advantageous to the case, private inheritance may be preferred over composition.