What is a template method pattern?
Defining the skeleton of an algorithm in an operation, and deferring these steps into subclasses, the template method allows subclasses to redefine some specific steps of the algorithm without altering the structure of an algorithm.
Good abstract concept Ah, genteel things are not pleasing, below I use a common example of life to illustrate it
is a drink machine, everyone is very familiar with it, the major shopping malls everywhere a thing, here for example, for example, we want to drink some kind of drink, as long as the corresponding beverage category, the drink will automatically come out.
Here we can abstract the imagination of the beverage in the machine's production process (here is just a simple example, not a dead-eyes ha)
Roughly, we can divide it into 4 steps.
① Boil ② brew drink ③ pour the drink into the cup ④ add seasoning
For example:
Coffee: Boil hot water--add coffee powder to brew--Pour the drink into the cup and add a little sugar
Milk tea: Boil hot water--add tea powder to brew--add the drink to the cup and add the coconut/pearl
It is not difficult to find that the steps in the process of the beverage ① boiling water, ③ the drink into the cup is repeated work, making bubble which kind of beverage is the same, then that is repeated work, we can set it as universal operation.
We just need to care about step ② and step ④.
Since the process of making the beverage is the 4 steps, so we can abstract it into a "make drink template" out, the following example, I use the code to illustrate
Drinktemplate.java (template Class)
This is a template for making drinks, which is the base class for making all the drinks.
We can encapsulate these 4 steps into a template method and implement the common steps inside
Because it avoids inheriting its subclasses to modify the overall authoring architecture, this method is decorated with the final modifier, like the famous "Hollywood Principle":D on ' t call us, we'll have to listen to the arrangement of the parent class
Since the steps ② and step ④ need to be based on the specific brew of the beverage to determine, so need to delay to the subclass to implement, where the protected modifier so that the subclass can be replicated, other methods can be directly written "dead" off, with the private modifier decoration, This allows code workers to pay more attention to their work without having to think about other factors.
1 Packagecom.lcw.template.test;2 3 Public Abstract classDrinktemplate {4 5 /**abstract base class6 * 7 * Make Beverage method template8 * 4 steps 1, boiling water 2, brewing beverage 3, pour the beverage into the Cup 4, add seasoning9 * Because steps 1, 3 is a common step, suitable for making any beverage, so you can write it deadTen * 2 and 4 steps, there are different options for different drinks, so you can defer it to the subclass de-duplication implementation (note the access modifier) One */ A Public Final voiddrinktemplate () { -Boilwater ();//Boiling Water -Brew ();//Brew Drinks thePourincup ();//Pour the drink into the cup -Addcondiments ();//Add Seasoning - } - + protected Abstract voidAddcondiments ();//add seasoning, because the seasoning of the beverage is different, so it can be deferred to sub-class implementation - + Private voidPourincup () { ASystem.out.println ("Pour the drink into the cup ..."); at } - - protected Abstract voidBrew ();//Brew drinks, because the materials used in the beverage are different, so you can delay to the sub-class implementation - - Private voidBoilwater () { -System.out.println ("Boiling water step in ..."); in } -}
Makecoffee.java (brewed coffee)
This is nothing to say, that is, inherit the abstract base class, and duplicate its abstract method
1 Packagecom.lcw.template.test;2 /**3 * 4 * @authorBalla_ Rabbit5 * Brew Coffee6 *7 */8 Public classMakecoffeeextendsDrinktemplate {9 Ten @Override One protected voidaddcondiments () { ASystem.out.println ("Add sugar ..."); - } - the @Override - protected voidBrew () { -System.out.println ("Add coffee powder to brew ..."); - } + -}
Makemilktea.java (Brew milk tea type)
1 Packagecom.lcw.template.test;2 /**3 * Brewing Milk tea4 * @authorBalla_ Rabbit5 *6 */7 Public classMakemilkteaextendsDrinktemplate {8 9 @OverrideTen protected voidaddcondiments () { OneSystem.out.println ("Add coconut fruit ..."); A } - - @Override the protected voidBrew () { -System.out.println ("Add tea powder to brew ..."); - } - +}
Test.java (Test Class)
1 Packagecom.lcw.template.test;2 3 Public classTest {4 5 /**6 * @authorBalla_ Rabbit7 */8 Public Static voidMain (string[] args) {9Drinktemplate coffee=NewMakecoffee ();Ten coffee.drinktemplate (); OneSystem.out.println ("*******************************"); ADrinktemplate milktea=NewMakemilktea (); - milktea.drinktemplate (); - } the -}
Look at the effect of the operation:
Haha, this kind of implementation of the class is not very clear ah, just need to make a copy of the method we need to care, greatly improve the reusability of the code.
But here's a problem to expose, the realization of brewing coffee is true, but there are always some people drink coffee is not sweetened, this is how to do?
This introduces the concept of a "hook" hook.
We can add hooks before and after a specific implementation, like a pre-method or a post-method, as in log technology, which requires logging before each business action is completed.
And this predecessor method, we can use a Boolean to make a judgment, and give it a default, to see the implementation of the method
Drinktemplate.java (template Class)
1 Packagecom.lcw.template.test;2 3 Public Abstract classDrinktemplate {4 5 /**abstract base class6 * 7 * Make Beverage method template8 * 4 steps 1, boiling water 2, brewing beverage 3, pour the beverage into the Cup 4, add seasoning9 * Because steps 1, 3 is a common step, suitable for making any beverage, so you can write it deadTen * 2 and 4 steps, there are different options for different drinks, so you can defer it to the subclass de-duplication implementation (note the access modifier) One */ A Public Final voiddrinktemplate () { -Boilwater ();//Boiling Water -Brew ();//Brew Drinks thePourincup ();//Pour the drink into the cup - if(condition () = =true){//If the condition allows, add seasoning, the default allows -Addcondiments ();//Add Seasoning - } + } - + protected Booleancondition () { A return true; at } - - protected Abstract voidAddcondiments ();//add seasoning, because the seasoning of the beverage is different, so it can be deferred to sub-class implementation - - Private voidPourincup () { -System.out.println ("Pour the drink into the cup ..."); in } - to protected Abstract voidBrew ();//Brew drinks, because the materials used in the beverage are different, so you can delay to the sub-class implementation + - Private voidBoilwater () { theSystem.out.println ("Boiling water step in ..."); * } $}
Test.java (Test Class)
1 Packagecom.lcw.template.test;2 3 Public classTest {4 5 /**6 * @authorBalla_ Rabbit7 */8 Public Static voidMain (string[] args) {9Drinktemplate coffee=NewMakecoffee ();Ten coffee.drinktemplate (); OneSystem.out.println ("Coffee is finished! "); ASystem.out.println ("*******************************"); -Drinktemplate milktea=NewMakemilktea (); - milktea.drinktemplate (); theSystem.out.println ("Milk tea production finished!" "); - } - -}
Look at the effect of this, haha, sugar-free coffee baked ~
Summary below:
First of all, the advantages of the template method pattern:
1, good package 2, good reuse, 3, shielding details 4, easy to maintain
As for the disadvantage, it is the inheritance problem, in Java can only inherit a parent class.
Process: Analyze scenes---step----Refactor code--important, complex algorithms, core algorithms designed as templates
Note the point:
Template method needs to be declared as public final
The private method is the basic logic
Protect abstract method is an extensible method
Hooks make template methods more flexible
Template method pattern for software Design patterns (JAVA)