As one of the design patterns of Java, Template Method summarizes its advantages and features in one word: Abstract steps
Next, record the understanding in the form of a question and answer
Question 1: now you want to make a cake, you will do many things. We will make the cake into the code as follows. Now you have a whim and come up with a production scheme. What should you do?
public class Cake { public static int METHOD_1 = 1; public static int METHOD_2 = 2; public void make(int method) { System.out.println("make start"); if (method == METHOD_1) { // Method 1 } else if (method == METHOD_2) { // Method 2 } System.out.println("make finish"); } }
Answer 1: you will not hesitate to say that a static field of method is added, followed by an if branch condition judgment and execution
public class Cake { ...... public static int METHOD_3 = 3; public void make(int method) { System.out.println("make start"); ...... } else if (method == METHOD_3) { // Method 2 } ...... System.out.println("make finish"); } }
Question 2: This is indeed a solution, but have you considered what to do if there are more than 100 lines in an if and you have a lot of production, and how to solve the lengthy problem?
Maybe you'll want me to add it. I'm familiar with it anyway. But if you are not a code editor, you get the class with N multiple strategies over 1000 lines. Do you make complaints about how to stack up? If you are a good designer or leader, can you review this set of code without wanting to optimize it?
For better scalability and readability, we can do this:
First of all, we should draw out common things to make a parent class (Base class). Secondly, the specific cake making is further realized by subclasses. For each production method, we will expand a subclass
If you carefully observe the Cake class, you will find that the make method is the core of the class, and the make() is the core code for executing the production. In order to leave the common things in the parent class (base class) as much as possible, we need to further split the code in make() into many sub steps. The methods are as follows:
public abstract class Cake { final void make() { makeStart();//log makingCakeGerm();//Make cake germ makingCream();//Making cream wipeCakeGerm();//Wipe cake germ piping();//Piping makeFinish();//log } private void makeStart() { System.out.println("make start"); } protected abstract String makingCakeGerm(); protected abstract String makingCream(); protected abstract String wipeCakeGerm(); protected abstract String piping(); private void makeFinish() { System.out.println("make finish"); } }
We can see that the steps in the make method have been further split and refined. First make the cake embryo, then make the cream, then apply it to the cake embryo, and finally mount the flowers
Let's pay attention to several details:
1. The cake class has become an abstract class. There is nothing to say. The methods are abstract
2. The make method adds a final modifier. You don't want subclasses to override this method to prevent the process from being changed
3. The abstraction of steps is the core of the template method. The specific implementation of steps is left to the subclasses. Each cake can be implemented independently with different subclasses, which greatly improves the readability and is very convenient to expand. You only need to implement a new subclass
Next, we implement the specific cake subclass:
We can think of it this way. The cake germ is basically the same, and the creaming is also a routine operation. The difference is what kind of cream to make and the style of mounting flowers
public abstract class Cake { final void make() { makeStart();//log makingCakeGerm();//Make cake germ makingCream();//Making cream wipeCakeGerm();//Wipe cake germ piping();//Piping makeFinish();//log } private void makeStart() { System.out.println("make start"); } private void makingCakeGerm() { System.out.println("making cake germ"); } protected abstract void makingCream();//Methods with different contents shall be implemented in subclasses private void wipeCakeGerm() { System.out.println("wipe cake germ"); } protected abstract void piping();//Methods with different contents shall be implemented in subclasses private void makeFinish() { System.out.println("make finish"); } }
Subclass implements cake A and cake B:
public class Cake_A extends Cake { @Override public void makingCream() { System.out.println("Vegetable cream Matcha flavor"); } @Override public void piping() { System.out.println("Mount eight flowers"); } } /******************************************/ public class Cake_B extends Cake { @Override public void makingCream() { System.out.println("Animal cream chocolate flavor"); } @Override public void piping() { System.out.println("Happy birthday"); } }
Finally, the Main class executes:
public class Test{ public static void main(String[] args){ Cake_A a = new Cake_A(); Cake_B b = new Cake_B(); a.make(); System.out.println("******************"); b.make(); } }
Take a look at the output:
I/System.out: make start I/System.out: Making cake germ I/System.out: Vegetable cream Matcha flavor I/System.out: Spread the cream on the cake I/System.out: Mount eight flowers I/System.out: make finish I/System.out: ****************** I/System.out: make start I/System.out: Making cake germ I/System.out: Animal cream chocolate flavor I/System.out: Spread the cream on the cake I/System.out: Happy birthday I/System.out: make finish
Summarize the advantages and disadvantages:
advantage:
- Enhanced reusability and readability
Put the same part of the code in the abstract parent class, and part of the implementation code is completed in the child class - Scalability enhancement
By adding subclasses to design new behaviors, a subclass is a behavior - It abides by the opening and closing principle, and realizes the reverse control by calling the extension behavior of its subclasses through the parent class
Disadvantages:
The disadvantages are obvious. If you have a large number of cake design methods, you need to implement many subclasses, and the complexity of system implementation will also be higher (but it is always better than writing together)
Application scenario:
In logic design, the unchanged (also known as common) logic is made in the parent class. The changed logic is in the parent class in the form of abstract method, which is inherited and implemented by the child class, and the subsequent changes and expansion should be completed by the child class to keep the parent class unchanged
----------------------------------------------------------
Answer time:
Q: some would say that the test class should be the parent type reference referring to the subclass object and then calling the parent type variable. make() method?
A: obviously, it is not necessary. The core idea of this design pattern is not polymorphism, and upward transformation can be realized. However, the core of template method lies in abstract steps and public reuse, so whether to use or not upward transformation has little impact
Q: some people will be confused after learning the strategy mode. Is this too similar to the template method?
A: don't doubt it's really similar! The difference is that the policy mode uses the interface to realize the expansibility of the algorithm, and the template method mode uses the inheritance to realize the expansibility of the method
This template method is almost over, but is it over?
The template method also has a finishing touch, which will be continued