Template Method pattern of software design pattern (JAVA)
Everyone is familiar with it. There is a thing that can be seen everywhere in major malls. Here is an example. For example, if we want to drink a certain kind of beverage, the beverage will automatically come out by pressing the corresponding beverage category. Here we can abstract and imagine the beverage production process in the machine (here is just a simple example, do not drill the horns) generally, we can divide it into four steps (1) boiling water (2) brewing drinks (3) pouring drinks into the cup (4) adding spices, for example, coffee: boil the hot water --> Add coffee powder for brewing --> pour the drink into the cup --> Add a little Sugar Milk Tea: boiling hot water --> adding milk tea powder to brew --> adding a drink to a cup --> adding coconut/pearl is not difficult to find. During the beverage production process, the following steps are repeated: (1) boiling water, (3) pouring a drink into the cup, which of the following drinks is the same, that is, to repeat the work, we can set it as a universal operation. We only need to care about steps 2 and 4. As the four steps are involved in beverage preparation, we can abstract them into a "beverage template, in the following example, we use code to describe DrinkTemplate. java (Template Class) is a template class for making drinks, that is, the base class for making all drinks. We can encapsulate these four steps into a template method, the general steps in the implementation should not inherit its subclass to modify the overall production architecture, so this method is modified with the final modifier, like the famous "Hollywood principles ": don't call us, we'll call you sub-classes need to listen from the parent class arrangement because step 2 and Step 4 need to be determined according to the specific beverage preparation, therefore, we need to delay the implementation to the subclass. Here the protected modifier is used so that the subclass can be rewritten. Other methods can directly write the "dead" modifier and use the private modifier to modify it, this allows the code staff to pay more attention to their work without having to consider other factors. Copy code 1 package com. lcw. template. test; 2 3 public abstract class DrinkTemplate {4 5/** abstract base class 6*7 * beverage method template 8*4 steps 1. Boiling Water 2. Brewing drinks 3. pouring drinks 4. Add seasoning 9 * because steps 1 and 3 are common steps, it is suitable for making any beverage, so you can write it to death for 10*2 and 4 steps, there are different choices for different drinks, so we can delay it to the subclass de-duplication implementation (pay attention to the access modifier) 11 */12 public final void drinkTempLate () {13 boilWater (); // boil 14 brew (); // brewed beverage 15 pourInCup (); // pour the beverage into the Cup 16 addCondiments (); // Add spices 17} 18 19 protected abstract void addCondim Ents (); // Add spices. Because the spices added by the beverage are different, you can delay it to the subclass to implement 20 21 private void pourInCup () {22 System. out. println ("pour the drink into the cup... "); 23} 24 25 protected abstract void brew (); // brewed beverage, because each beverage uses different materials, so we can delay to the subclass to implement 26 27 private void boilWater () {28 System. out. println ("boiling water in progress... "); 29} 30} copy the code MakeCoffee. java (brewing coffee class) is nothing to mention. It inherits the abstract base class and rewrites its abstract method to copy code 1 package com. lcw. template. test; 2/** 3*4 * @ author Balla _ rabbit 5 * brewed coffee 6*7 */8 Public class MakeCoffee extends DrinkTemplate {9 10 @ Override11 protected void addCondiments () {12 System. out. println ("sugar... "); 13} 14 15 @ Override16 protected void brew () {17 System. out. println ("add coffee powder for brewing... "); 18} 19 20} copy the code MakeMilkTea. java (brewed milk tea) Copy code 1 package com. lcw. template. test; 2/** 3 * brewed milk tea 4 * @ author Balla _ rabbit 5*6 */7 public class MakeMilkTea extends DrinkTemplate {8 9 @ Override10 Protected void addCondiments () {11 System. out. println ("plus coconut... "); 12} 13 14 @ Override15 protected void brew () {16 System. out. println ("add milk tea powder for brewing... "); 17} 18 19} copy the code Test. java (test class) Copy code 1 package com. lcw. template. test; 2 3 public class Test {4 5/** 6 * @ author Balla _ rabbit 7 */8 public static void main (String [] args) {9 DrinkTemplate coffee = new MakeCoffee (); 10 coffee. drinkTempLate (); 11 System. out. print Ln ("*******************************"); 12 DrinkTemplate milkTea = new MakeMilkTea (); 13 milkTea. drinkTempLate (); 14} 15 16} copy the code to check the running effect. Haha, is this implementation class clearly written? You only need to rewrite the methods we need to care about, this greatly improves code reusability. But there is a problem that is revealed here. The implementation of coffee brewing is true, but some people do not need sugar when drinking coffee. What should I do? Here we introduce a "hook" hook concept. We can add hooks before and after a specific implementation method. This is like a pre-method or post-method, just like a log technology, logs must be recorded before each business action is completed. This method uses a Boolean to determine the result and provides a default value for DrinkTemplate. java (Template Class) Copy code 1 package com. lcw. template. test; 2 3 public abstract class DrinkTemplate {4 5/** abstract base class 6*7 * beverage method template 8*4 steps 1. Boiling Water 2. Brewing drinks 3. pouring drinks 4. Add seasoning 9 * because steps 1 and 3 are common steps, it is suitable for making any beverage, so you can write it to death for 10*2 and 4 steps, there are different choices for different drinks, so we can delay it to the subclass de-duplication implementation (pay attention to the access modifier) 11 */12 public fina L void drinkTempLate () {13 boilWater (); // boiling water 14 brew (); // brewed beverage 15 pourInCup (); // pour the beverage into the Cup 16 if (condition () = true) {// Add seasoning if conditions permit. 17 addCondiments () is allowed by default; // Add seasoning 18} 19} 20 21 protected boolean condition () {22 return true; 23} 24 25 protected abstract void addCondiments (); // Add spices because the spices added to the beverage are different, therefore, you can delay to the subclass to implement 26 27 private void pourInCup () {28 System. out. println ("pour the drink into the cup... "); 29} 30 31 protected abstract void brew ();// Brewed drinks, because the materials used for the drinks are different, you can delay to the subclass to implement 32 33 private void boilWater () {34 System. out. println ("boiling water in progress... "); 35} 36} copy the code Test. java (test class) Copy code 1 package com. lcw. template. test; 2 3 public class Test {4 5/** 6 * @ author Balla _ rabbit 7 */8 public static void main (String [] args) {9 DrinkTemplate coffee = new MakeCoffee (); 10 coffee. drinkTempLate (); 11 System. out. println ("coffee production is complete! "); 12 System. out. println ("*******************************"); 13 DrinkTemplate milkTea = new MakeMilkTea (); 14 milkTea. drinkTempLate (); 15 System. out. println ("milk tea is ready! "); 16} 17 18}