1+ // cppcheck-suppress-file [functionStatic]
2+
3+ // is a behavioral design pattern that defines the skeleton of an algorithm in the `superclass`
4+ // but lets `subclasses` override specific steps of the algorithm without changing its structure.
5+ // Appicability:
6+ // (*) when you want to let clients extend only particular steps of an algorithm, but not the whole algorithm or its structure.
7+ // (**) when you have several classes that contain almost identical algorithms with some minor differences.
8+ // As a result, you might need to modify all classes when the algorithm changes.
9+ // (**) when a behavior makes sense only in some classes of a class hierarchy, but not in others.
10+ // UML: docs/uml/patterns_behavioral_templatemethod.drawio.svg
11+
12+ #include < iostream>
13+
14+ namespace
15+ {
16+ namespace TemplateMethod
17+ {
18+ class AbstractClass
19+ {
20+ public:
21+ virtual ~AbstractClass () = default ;
22+ // Template Method (non-virtual => cannot be overridden)
23+ // Defines the algorithm's skeleton and ensures subclasses cannot change the flow.
24+ void templateMethod () const
25+ {
26+ baseOperation1 ();
27+ abstractMethod1 ();
28+ hookOperation1 ();
29+
30+ baseOperation2 ();
31+ abstractMethod2 ();
32+ hookOperation2 ();
33+ }
34+
35+ protected:
36+ // 1. Base operations: These have full implementations and cannot be overridden.
37+ void baseOperation1 () const
38+ {
39+ // Common logic step 1
40+ std::cout << " [AbstractClass]\t Executed base operation - 1\n " ;
41+ }
42+
43+ void baseOperation2 () const
44+ {
45+ // Common logic step 2
46+ std::cout << " [AbstractClass]\t Executed base operation - 2\n " ;
47+ }
48+
49+ // 2. Hook methods: Subclasses may override them to extend behavior, but overriding is optional.
50+ virtual void hookOperation1 () const {}
51+ virtual void hookOperation2 () const {}
52+
53+ // 3. Abstract methods: Subclasses MUST provide implementations.
54+ virtual void abstractMethod1 () const = 0;
55+ virtual void abstractMethod2 () const = 0;
56+ };
57+
58+ class ConcreteClass1 : public AbstractClass
59+ {
60+ public:
61+ void abstractMethod1 () const override
62+ {
63+ std::cout << " [ConcreteClass1]\t Implemented Operation - 2\n " ;
64+ }
65+
66+ void abstractMethod2 () const override
67+ {
68+ std::cout << " [ConcreteClass1]\t Implemented Operation - 2\n " ;
69+ }
70+
71+ void hookOperation1 () const override
72+ {
73+ std::cout << " [ConcreteClass1]\t Overridden Hook - 1\n " ;
74+ }
75+ };
76+
77+ class ConcreteClass2 : public AbstractClass
78+ {
79+ public:
80+ void abstractMethod1 () const override
81+ {
82+ std::cout << " [ConcreteClass2]\t Implemented Operation - 2\n " ;
83+ }
84+
85+ void abstractMethod2 () const override
86+ {
87+ std::cout << " [ConcreteClass2]\t Implemented Operation - 2\n " ;
88+ }
89+ };
90+
91+ namespace Client
92+ {
93+ void clientCode (const AbstractClass *clazz)
94+ {
95+ clazz->templateMethod ();
96+ }
97+ }
98+ void run ()
99+ {
100+ std::cout << " \t [ConcreteClass1] Executed templateMethod\n " ;
101+ AbstractClass *clazz1 = new ConcreteClass1 ();
102+ Client::clientCode (clazz1);
103+
104+ std::cout << " \t [ConcreteClass1] Executed templateMethod\n " ;
105+ AbstractClass *clazz2 = new ConcreteClass2 ();
106+ Client::clientCode (clazz2);
107+
108+ delete clazz1;
109+ delete clazz2;
110+ }
111+ }
112+ }
113+
114+ struct TemplateMethodAutoRunner
115+ {
116+ TemplateMethodAutoRunner ()
117+ {
118+ std::cout << " \n --- TemplateMethod Pattern Example ---\n " ;
119+ TemplateMethod::run ();
120+ }
121+ };
122+
123+ static TemplateMethodAutoRunner instance;
0 commit comments