Hello everyone!! After few months, I’m again! 😃😎🙂 I had a lot of others activities. Today is about the template method design pattern. Is a lot of to describe but about this is further in the post. 🙂
Admission
I was gone for a long time, but I probably needed some rest. Is a lot of to talking, example I will be starting my own company in IT branch in not so far future, I was talking with some people about few ideas mobile applications, and we have a few expectant investors, so I hope that will be successful 🙂 but we’ll see, still is a lot of time on that 🙂 But enough about me as you see I had a lot of work. Let’s back to the topic, today is about the template method design pattern, which in brief is used as a program skeleton. I feel like Arnold 😂😂
Discussion
The design pattern consists of at least two classes. In the AbstractClass class an program skeleton is defined and it is used by the client, there are methods that are abstract, so there are variables and we can change their behavior in each class that inherits from the AbstractClass class, there are also methods that have already defined logic, that is, they are immutable, their behavior can not be changed. And all these methods are called in the tempateMethod() method, which is also defined in the AbstractClass class.
The template method is used very often in various frameworks. If someone noticed the connection template method with the Inversion of Control principle, it congratulates the perceptiveness 🙂. Note that the AbstractClass class is, you can say the class framework is defined in it, the logic is used by the client and the code in this class calls the client code, i.e. complies with the Hollywood principle.
Intent
- Defining the skeleton of the algorithm.
- Separating part of the logic to classes that inherit from the AbstractClass class (base class) without changing the basic structure of the algorithm.
- Implementing invariant part of the algorithm.
Problem
You have created some part of the code that is hard to expand and you want this code to be easy to modify, or you have a code that has many similarities, but also defines common implementations or interfaces that can not be used. In all these cases, it is worth to use the template method 🙂 design pattern.
Use when:
- You want, for example, to have a program that will be open to extensions, but closed to modifications, i.e. you want to have a piece of the program that will be expandable without changing the existing logic, i.e. the template method pattern also applies the second solid principle. 🙂
- You create your own framework that other people will use, passing some arguments to it and that will return a specific answer.
Structure
In this section, I will show the UML diagram of the template method:
The whole code that you can use again is in the FrameworkClass class and the methods that extend the framework logic are ApplicationClassOne and ApplicationClassTwo.
The template method is also used in sorting algorithms, the implementation principle of which is described in the diagram below:
The logic part of the sorting algorithm is invariant, such as the sort() or returnArray() methods, because they always work the same way, there is no need to expand anything, only the compare() method is extended to add sorting descending and sorting ascending.
Let’s see now how it looks like in the code, first we will see what the AbstractClass class looks like, ie the most important class in the pattern:
namespace TemplateMethodSchema
{
abstract class AbstractClass
{
public void TemplateMethod()
{
StepOne();
StepTwo();
Console.WriteLine("");
}
public abstract void StepOne();
public abstract void StepTwo();
}
}
And let’s see the classes that inherit from the AbstractClass class.
namespace TemplateMethodSchema
{
class ConcreteClassA : AbstractClass
{
public override void StepOne()
{
Console.WriteLine("ConcreteClassA.PrimitiveOperation1()");
}
public override void StepTwo()
{
Console.WriteLine("ConcreteClassA.PrimitiveOperation2()");
}
}
class ConcreteClassB : AbstractClass
{
public override void StepOne()
{
Console.WriteLine("ConcreteClassB.PrimitiveOperation1()");
}
public override void StepTwo()
{
Console.WriteLine("ConcreteClassB.PrimitiveOperation2()");
}
}
}
We see that the abstract methods that are defined in the AbstractClass class are adapted to the classes that inherit from the AbstractClass class.
And finally, the customer.
namespace TemplateMethodSchema
{
class Program
{
static void Main(string[] args)
{
AbstractClass aA = new ConcreteClassA();
aA.TemplateMethod();
AbstractClass aB = new ConcreteClassB();
aB.TemplateMethod();
Console.ReadKey();
}
}
}
In the client, we call the TemplateMethod() method, which calls all the other methods in the AbstractClass class, we see the using of the IoC principle, framework invokes the client’s methods.
Result
Example
An example of a template method is the employee’s daily routine.
We can see here that some of the activities of some workers are the same, others are not. In this example, it’s a good idea to use the template method. Let’s see how it is looks like in the code. Let’s start from the main class AbstractClass, in this example it is the Worker class.
namespace Workers
{
abstract class Worker
{
protected void goToWork()
{
Console.WriteLine("Go to work at eight a.m");
}
protected void work()
{
Console.WriteLine("Work for eight hours");
}
protected void returnToHome()
{
Console.WriteLine("Return from work at sixteen p.m");
}
protected abstract void getUp();
protected abstract void eatBreakfast();
protected abstract void relax();
protected abstract void sleep();
public void DailyRoutine()
{
goToWork();
work();
returnToHome();
getUp();
eatBreakfast();
relax();
sleep();
Console.WriteLine("");
}
}
}
This class is similar to the AbstractClass from the previous example, but that class is extended by invariant methods goToWork(), work(), returnToHome() the rest of the code is similar to the previous example. We assume that all workers go to work, work and return to home at the same hours, so there is no need to make this methods as a changeable.
Let’s see now the FireFighter, Lumberjack, Postman and the Manager classes.
FireFighter class
namespace Workers
{
class FireFighter:Worker
{
protected override void getUp()
{
Console.WriteLine("Get up at five a.m");
}
protected override void eatBreakfast()
{
Console.WriteLine("Eat breakfast at six a.m");
}
protected override void relax()
{
Console.WriteLine("Take a break at eight p.m");
}
protected override void sleep()
{
Console.WriteLine("Go sleep at twelve p.m");
}
}
}
Lumberjack class
namespace Workers
{
class Lumberjack : Worker
{
protected override void getUp()
{
Console.WriteLine("Get up at half past seven a.m. Flax...");
}
protected override void eatBreakfast()
{
Console.WriteLine("Eat during work...");
}
protected override void relax()
{
Console.WriteLine("Take a break at sixteen p.m. Not very ambitious...");
}
protected override void sleep()
{
Console.WriteLine("Go sleep at eight p.m");
}
}
}
Postman class
namespace Workers
{
class Postman : Worker
{
protected override void getUp()
{
Console.WriteLine("Get up at six a.m");
}
protected override void eatBreakfast()
{
Console.WriteLine("Eat breakfast at seven a.m");
}
protected override void relax()
{
Console.WriteLine("Take a break at half past sixteen p.m");
}
protected override void sleep()
{
Console.WriteLine("Go sleep at eleven p.m");
}
}
}
Manager class
namespace Workers
{
class Manager : Worker
{
protected override void getUp()
{
Console.WriteLine("Get up at four a.m. Ambitious :)");
}
protected override void eatBreakfast()
{
Console.WriteLine("Eat breakfast at six a.m");
}
protected override void relax()
{
Console.WriteLine("Take a break at ten p.m. Busy bee :)");
}
protected override void sleep()
{
Console.WriteLine("Go sleep at midnight");
}
}
}
As you can see, these classes only extend the methods getUp(), eatBreakfast(), relax(), sleep(), each employee adjusts the remaining hours of activity to himself.
At the end the client.
namespace Workers
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("FireFighter");
Worker firefighter = new FireFighter();
firefighter.DailyRoutine();
Console.WriteLine("Lumberjack");
Worker lumberjack = new Lumberjack();
lumberjack.DailyRoutine();
Console.WriteLine("Manager");
Worker manager = new Manager();
manager.DailyRoutine();
Console.WriteLine("Postman");
Worker postman = new Postman();
postman.DailyRoutine();
Console.ReadKey();
}
}
}
And we call the DailyRoutine() method in each class.
Result
Real-life example
Real-life example can be the document generator. In the console we will make generators of HTML and XML documents. In order as in the previous example, let’s start from the main class, in this example main class is the DocumentGenerator class.
namespace DocumentGenerator
{
abstract class DocumentGenerator
{
public abstract void generateHeader();
public abstract void generateBody();
public abstract void generateDetails();
public void generateDocument()
{
generateHeader();
generateDetails();
generateBody();
}
}
}
Nothing new 🙂
Let’s see the classes that extend a generateHeader(), generateBody() and generateDetails() methods.
First HTMLDocGenerator
namespace DocumentGenerator
{
class HTMLDocGenerator : DocumentGenerator
{
public string documentDetails;
public override void generateDetails()
{
documentDetails = "<header>\n\n</header>\n\n<footer>\n\n</footer>\n\n";
}
public override void generateBody()
{
Console.WriteLine("<body>\n\n" + documentDetails + "</body>");
}
public override void generateHeader()
{
Console.WriteLine("<head>\n\n</head>");
}
}
}
And XMLDocGenerator class
namespace DocumentGenerator
{
class XMLDocGenerator : DocumentGenerator
{
public string documentDetails;
public override void generateDetails()
{
documentDetails = "<name>\n\nProduct one\n\n</name>";
}
public override void generateBody()
{
Console.WriteLine("<product>\n\n" + documentDetails + "\n\n</product>");
}
public override void generateHeader()
{
Console.WriteLine("<?xml version= " + 1.0 + " ?>");
}
}
}
And the client
namespace DocumentGenerator
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("HTML Document\n");
HTMLDocGenerator htmldocgenerator = new HTMLDocGenerator();
htmldocgenerator.generateDocument();
Console.WriteLine("\nXML Document\n");
XMLDocGenerator xmldocgenerator = new XMLDocGenerator();
xmldocgenerator.generateDocument();
Console.ReadKey();
}
}
}
This is a simple example, I think there is nothing to explain 🙂 If I’m wrong give to know in the comments.
Result
Relations with other design patterns
- Template Method uses inheritance to vary part of an algorithm. Strategy uses delegation to vary the entire algorithm.
- Strategy modifies the logic of individual objects. Template Method modifies the logic of an entire class.
Summary
That’s all about Template method🙂.
Link to github with the whole code from this article: https://github.com/Slaw145/TemplateMethodTutorial
This content also you can find on my blog http://devman.pl/programtech/design-patterns-template-method/
In the next article, we will talk about the Observer pattern.
And NECESSERILY join the DevmanCommunity community on fb, part of the community is in one place 🙂
– site on fb: Devman.pl-Sławomir Kowalski
– group on fb: DevmanCommunity
Ask, comment underneath at the end of the post, share it, rate it, whatever you want🙂.
Now a lot is happening with me, so entries will be more or less every two to three weeks, on the fb page and on the group about every two. I will send newsletters more or less every two weeks, so many things are happening that it’s hard to predict when exactly I will do it. 🙂
Illustrations, pictures and diagrams are from: https://sourcemaking.com/design_patterns/template_method