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_visitor.drawio.svg
11+
12+ #include < iostream>
13+ #include < string>
14+ #include < vector>
15+
16+ namespace
17+ {
18+ namespace TemplateMethod
19+ {
20+ class AbstractClass
21+ {
22+ public:
23+ virtual ~AbstractClass () = default ;
24+ // Template Method (non-virtual => cannot be overridden)
25+ // Defines the algorithm's skeleton and ensures subclasses cannot change the flow.
26+ void templateMethod () const
27+ {
28+ baseOperation1 ();
29+ abstractMethod1 ();
30+ hookOperation1 ();
31+
32+ baseOperation2 ();
33+ abstractMethod2 ();
34+ hookOperation2 ();
35+ }
36+
37+ protected:
38+ // 1. Base operations: These have full implementations and cannot be overridden.
39+ void baseOperation1 () const
40+ {
41+ // Common logic step 1
42+ std::cout << " [AbstractClass]\t Executed base operation - 1\n " ;
43+ }
44+
45+ void baseOperation2 () const
46+ {
47+ // Common logic step 2
48+ std::cout << " [AbstractClass]\t Executed base operation - 2\n " ;
49+ }
50+
51+ // 2. Hook methods: Subclasses may override them to extend behavior, but overriding is optional.
52+ virtual void hookOperation1 () const {}
53+ virtual void hookOperation2 () const {}
54+
55+ // 3. Abstract methods: Subclasses MUST provide implementations.
56+ virtual void abstractMethod1 () const = 0;
57+ virtual void abstractMethod2 () const = 0;
58+ };
59+
60+ class ConcreteClass1 : public AbstractClass
61+ {
62+ public:
63+ void abstractMethod1 () const override
64+ {
65+ std::cout << " [ConcreteClass1]\t Implemented Operation - 2\n " ;
66+ }
67+
68+ void abstractMethod2 () const override
69+ {
70+ std::cout << " [ConcreteClass1]\t Implemented Operation - 2\n " ;
71+ }
72+
73+ void hookOperation1 () const override
74+ {
75+ std::cout << " [ConcreteClass1]\t Overridden Hook - 1\n " ;
76+ }
77+ };
78+
79+ class ConcreteClass2 : public AbstractClass
80+ {
81+ public:
82+ void abstractMethod1 () const override
83+ {
84+ std::cout << " [ConcreteClass2]\t Implemented Operation - 2\n " ;
85+ }
86+
87+ void abstractMethod2 () const override
88+ {
89+ std::cout << " [ConcreteClass2]\t Implemented Operation - 2\n " ;
90+ }
91+ };
92+
93+ namespace Client
94+ {
95+ void clientCode (const AbstractClass *clazz)
96+ {
97+ clazz->templateMethod ();
98+ }
99+ }
100+ void run ()
101+ {
102+ std::cout << " \t [ConcreteClass1] Executed templateMethod\n " ;
103+ AbstractClass *clazz1 = new ConcreteClass1 ();
104+ Client::clientCode (clazz1);
105+
106+ std::cout << " \t [ConcreteClass1] Executed templateMethod\n " ;
107+ AbstractClass *clazz2 = new ConcreteClass2 ();
108+ Client::clientCode (clazz2);
109+
110+ delete clazz1;
111+ delete clazz2;
112+ }
113+ }
114+ }
115+
116+ struct TemplateMethodAutoRunner
117+ {
118+ TemplateMethodAutoRunner ()
119+ {
120+ std::cout << " \n --- TemplateMethod Pattern Example ---\n " ;
121+ TemplateMethod::run ();
122+ }
123+ };
124+
125+ static TemplateMethodAutoRunner instance;
0 commit comments