Single Template Method
![](https://yuml.me/collard/design-pattern-template-abstract-concret.svg)
- ConcreteClass has to subclass the entire AbstractClass
- The ConcreteClass has to include any AbstractClass dependencies
- For each abstract method, ConcreteClass must provide a definition
Multiple Template Methods
![](https://yuml.me/collard/handler-abstract-class-real.svg)
- What about if there is more than one template method?
- ConcreteClassA has to implement all AbstractClass abstract methods, i.e.,
primitiveOperationA1()
, primitiveOperationA2()
, primitiveOperationB1()
, and primitiveOperationB2()
, even if only interested in templateMethodA()
- Similarly for ConcreteClassB
- The only class this works fine for is ConcreteClassAB
Goal
- Separate primitive operations for a particular purpose from the rest of the class interface allows for the decoupling of the rest of the class
- Subclass the set of primitive operations instead of the entire class
- Reduces coupling and has multiple template methods
Solution
![](/images/HandlersSolution.svg)
Solution
![](/images/HandlersSolution.svg)
- AbstractHandler has only essential dependencies for the interface and does not have the dependencies of the MainClass
- ConcreteHandler is derived from AbstractHandler, so it does not share the dependencies of MainClass
Solution: Class Structure
Multiple Handlers
![](https://yuml.me/collard/handler-multiple-handlers.svg)
Standard Handlers
![](https://yuml.me/collard/handler-standard.svg)
- Can provide standard, off-the-shelf handlers
- Clients can pick these or even further subclass them
- Users can even create their own sets of off-the-shelf handlers
Advantages
- Replaces subclassing a large, complex class with subclassing a cohesive interface
- Handlers are almost always all pure virtual or empty methods
- The only dependencies that handlers have are for parameters and return types
- Allows multiple types of handlers, which the design can mix in new ways
- Allows standard handlers to be created and shared
- Easier to test, as can test individual handlers
Template Method Includes
![](/images/DockerReportTemplate.svg)
DockerReport: Handler Design
![](/images/DockerReportHandler.svg)
DockerReport: Template Method & Handler Comparison
![](/images/DockerReportTemplate.svg)
![](/images/DockerReportHandler.svg)
Handler Includes
![](/images/DockerReportHandler.svg)
Decoupling YAMLParser
![](/images/DockerReportHandlerParseEngine.svg)
Decoupling YAMLParser
![](/images/DockerReportHandlerParseEngine.svg)
Decoupling YAMLParser
ParserEngine
can be a free function, a static method of a class, a method of a class, or even part of a framework
- The implementation of
ParserEngine
(i.e., .cpp
files) are the ones that use YAMLParser
- The interface of
ParserEngine
(i.e., .hpp
files) does not use or include YAMLParser
and is completely decoupled from YAMParser
- The interface of
ParserEngine
(i.e., .hpp
files) does use YAMLParserHandler
as a parameter