no_mkd
I. What is the Template Method Pattern?
First, the Template Method Pattern is used to encapsulate the algorithm skeleton, that is, the algorithm process.
Since it's called a template, it certainly allows extended classes to apply this template. To accommodate changes, it must also allow extended classes to make some modifications.
That's exactly the case. The Template Method Pattern encapsulates the algorithm process but allows subclasses to be responsible for implementing certain step details.
II. An Example
Suppose we want to open a fried sauce noodle shop that allows franchising. We have an exclusive secret sauce recipe and a unique production process. The delicacy is one of a kind on Earth. Most people on Earth eat our fried sauce noodles every day, so we have a large number of franchisees.
To make a profit, of course, we cannot disclose the production process and sauce recipe. However, due to regional differences among franchisees, there are differences in production details. For example, people in Beijing prefer thin, hard noodles, while people in Shaanxi prefer wide, soft noodles. We cannot protect the recipe by making Beijing franchisees continue to sell our wide noodles.
So we need to protect the production process and secret recipe, allowing no one to modify them, while making the noodle preparation and cooking methods public, allowing franchisees to modify them. So, how to implement such a requirement?
That's right, the Template Method is born for this.
First, we need to establish a template class, protecting what should be protected and making public what should be public:
package TemplateMethodPattern;/**
-
@author ayqy
-
Define fried sauce noodle template class */ public abstract class Noodles { public void cook(){ //Make noodles makeNoodles(); //Make sauce makeSauce(); //Boil noodles boilNoodles(); //Add sauce addSauce(); }
/**
- Protect the secret sauce */ private void makeSauce(){ System.out.println("Make a portion of exclusive secret sauce"); }
/**
- Protect the sauce dosage */ private void addSauce(){ System.out.println("Add appropriate amount of secret sauce"); }
public abstract void makeNoodles(); public abstract void boilNoodles(); }
Once the template is defined, 90% of the work is done. Now let's implement the concrete classes.
Beijing Fried Sauce Noodles:
package TemplateMethodPattern;/**
-
@author ayqy
-
Implement Beijing fried sauce noodle concrete class */ public class BJNoodles extends Noodles{
@Override public void makeNoodles() { System.out.println("Make a portion of handmade noodles with Beijing characteristics"); }
@Override public void boilNoodles() { System.out.println("Boil noodles according to Beijing-style cooking method"); } }
Shaanxi Fried Sauce Noodles:
package TemplateMethodPattern;/**
-
@author ayqy
-
Implement Shaanxi fried sauce noodle concrete class */ public class SXNoodles extends Noodles{
@Override public void makeNoodles() { System.out.println("Make a portion of handmade noodles with Shaanxi characteristics"); }
@Override public void boilNoodles() { System.out.println("Boil noodles according to Shaanxi-style cooking method"); } }
With these concrete classes, we can distribute them to franchisees according to region.
III. Effect Example
First, implement a test class:
package TemplateMethodPattern;/**
-
@author ayqy
-
Implement a test class */ public class Test { public static void main(String[] args){ //Create Beijing fried sauce noodle object Noodles bjnoodles = new BJNoodles(); //Create Shaanxi fried sauce noodle object Noodles sxnoodles = new SXNoodles();
System.out.println("Beijing fried sauce noodle production process:"); bjnoodles.cook();//Make a portion of Beijing fried sauce noodles System.out.println("\nShaanxi fried sauce noodle production process:"); sxnoodles.cook();//Make a portion of Shaanxi fried sauce noodles} }
Running result:

IV. A Little More Thinking
In the example above, we easily achieved encapsulation of the algorithm skeleton and allowed extended classes to customize certain step details. It seems easy and perfect.
Well, let's change the requirement:
Recently, green and healthy living has been advocated. Everyone likes to eat some vegetables. Our traditional fried sauce noodles have to keep up with the times. After preparation, we need to add some vegetables. But the problem is that some places don't like to add vegetables. They are accustomed to the flavor of the old-brand fried sauce noodles and firmly reject vegetables. So we cannot simply change the production process by adding a step to add vegetables. It would be great if we could define an optional operation in the template, allowing franchisees to choose whether to add some vegetables.
So, we need to make a small change to the previous template:
package TemplateMethodPattern;/**
-
@author ayqy
-
Define fried sauce noodle template class */ public abstract class Noodles { private boolean wantVegetables = false;//Want vegetables or not
public void setWantVegetables(boolean wantVegetables) { this.wantVegetables = wantVegetables; }
public void cook(){ //Make noodles makeNoodles(); //Make sauce makeSauce(); //Boil noodles boilNoodles();
//Want to add some vegetables or not if(wantVegetables) addVegetables(); //Add sauce addSauce();}
/**
- Protect the secret sauce */ private void makeSauce(){ System.out.println("Make a portion of exclusive secret sauce"); }
/**
- Protect the sauce dosage */ private void addSauce(){ System.out.println("Add appropriate amount of secret sauce"); }
/**
- Add seasonal vegetables */ public void addVegetables(){ //Empty implementation }
public abstract void makeNoodles(); public abstract void boilNoodles(); }
Note that to add an optional operation, we did the following things:
- Define a flag variable (select/not select)
- Provide a setter for the flag variable for extended classes to choose
- Modify the algorithm skeleton to add a new optional step
- Provide an empty implementation for the new step (Note: this step is very important. Providing an empty implementation instead of defining an abstract method avoids modifications to existing extended classes. This is called a Hook in Template Method Pattern terminology)
V. Template Method Pattern vs. Strategy Pattern
Both patterns are used to encapsulate algorithms. Let's compare them:
| Strategy Pattern | Template Method Pattern | |
| Concept | Encapsulate algorithm steps, allowing subclasses to choose existing strategies (step details) | Encapsulate algorithm skeleton (process), allowing subclasses to be responsible for implementing certain details |
| Implementation Method | Implemented using composition | Implemented using inheritance |
| Goal | Achieves selection of algorithm steps | Achieves algorithm process control |
| Highlight | Supports dynamically changing steps (strategies) at runtime | Supports dynamically changing algorithm process at runtime (implemented using hook) |
| Concrete Steps | Find out the easily changeable similar algorithm details (steps), then define an algorithm family (interface) to encapsulate them | Abstract the algorithm skeleton and encapsulate it in the base class (template class) |
| Summary | Encapsulate steps | Encapsulate process |
For example:
Suppose there is an algorithm with the process A->B->C->D. The concrete implementation of step C may have three different methods: c1, c2, c3.
Strategy Pattern:
- Define a behavior interface C with an execute method
- Implement concrete classes c1, c2, c3 extending interface C (c1, c2, c3 three behaviors for the caller to choose)
- Add a property in the base class with type interface C and provide a setter
- Concrete classes extending the base class will dynamically change behavior by calling the setter
Template Method Pattern:
- Define a base class (template class) with the algorithm process defined in the base class (encapsulate the process)
- Define step C as an abstract method in the base class
- Concrete classes extending the base class will provide their own implementations (c1, c2, c3 or others)
No comments yet. Be the first to share your thoughts.