preface
In this chapter, we will learn two patterns of behavioral patterns, strategy pattern and Template Pattern.
Strategy mode
brief introduction
A Strategy Pattern belongs to the behavior pattern of an object. Its purpose is to encapsulate each algorithm into an independent class with a common interface for a group of algorithms, so that they can be replaced with each other. The policy mode allows the algorithm to change without affecting the client.
Its main purpose is to replace the if else statement writing method by defining similar algorithms, and they can replace each other at any time.
The policy pattern is mainly composed of these three roles: context, abstract strategy and concrete strategy.
- Context: holds a reference to a policy class and provides it to the client for use.
- Abstract strategy role: This is an abstract role, which is usually implemented by an interface or abstract class. This role gives the interfaces required for all specific policy classes.
- Concrete strategy: encapsulates relevant algorithms or behaviors.
The example diagram is as follows:
In order to facilitate understanding, let's take the calculation method used when we first learned Java.
When using a calculator for calculation, the method of addition, subtraction, multiplication and division is often used. If we want to get the sum of two numbers, we need to use the "+" symbol to get the difference of subtraction, the "-" symbol and so on. Although we can use if/else to write a general method through string comparison, each time the calculated symbol increases, we have to add the corresponding code to the original method. If the subsequent calculation methods are added, modified or deleted, it will make the subsequent maintenance difficult.
However, among these methods, we find that the basic method is fixed. At this time, we can develop through the policy mode, which can effectively avoid judging through if/else, and can be flexibly adjusted even if other calculation rules are added later.
First, define an abstract policy role and have a calculation method.
interface CalculateStrategy { int doOperation(int num1, int num2); }
Then define the specific policy roles of addition, subtraction, multiplication and division and implement the methods.
Then the code is as follows:
class OperationAdd implements CalculateStrategy { @Override public int doOperation(int num1, int num2) { return num1 + num2; } } class OperationSub implements CalculateStrategy { @Override public int doOperation(int num1, int num2) { return num1 - num2; } } class OperationMul implements CalculateStrategy { @Override public int doOperation(int num1, int num2) { return num1 * num2; } } class OperationDiv implements CalculateStrategy { @Override public int doOperation(int num1, int num2) { return num1 / num2; } }
Finally, define an environment role and provide a computing interface for the client to use.
The code is as follows:
class CalculatorContext { private CalculateStrategy strategy; public CalculatorContext(CalculateStrategy strategy) { this.strategy = strategy; } public int executeStrategy(int num1, int num2) { return strategy.doOperation(num1, num2); } }
After writing, let's test it.
The test code is as follows:
public static void main(String[] args) { int a=4,b=2; CalculatorContext context = new CalculatorContext(new OperationAdd()); System.out.println("a + b = "+context.executeStrategy(a, b)); CalculatorContext context2 = new CalculatorContext(new OperationSub()); System.out.println("a - b = "+context2.executeStrategy(a, b)); CalculatorContext context3 = new CalculatorContext(new OperationMul()); System.out.println("a * b = "+context3.executeStrategy(a, b)); CalculatorContext context4 = new CalculatorContext(new OperationDiv()); System.out.println("a / b = "+context4.executeStrategy(a, b)); }
Output result:
a + b = 6 a - b = 2 a * b = 8 a / b = 2
Advantages of policy mode:
It has good expansibility and can be implemented by adding new classes to the new algorithm without modifying the object structure;
It has good flexibility and can switch the algorithm freely;
Disadvantages of policy mode:
Using more policy classes will increase the complexity of the system.;
The client must know all policy classes before calling;
Usage scenario:
If there are many classes in a system, and the only difference between them is their behavior, then using the policy pattern can dynamically let an object choose one behavior among many behaviors;
A system needs to dynamically choose one of several algorithms;
If an object has many behaviors, if you don't use appropriate patterns, these behaviors have to be realized by multiple conditional selection statements;
Template mode
brief introduction
In Template Pattern, an abstract class publicly defines the way / template of the method executing it. Its subclasses can override the method implementation as needed, but the call will be made in the way defined in the abstract class. This type of design pattern belongs to behavioral pattern. Define the skeleton of the algorithm in an operation and delay some steps to subclasses.
The main idea of template mode is to make a template and provide it to the client for calling. In addition to the resume template and contract template we often use in life, there are also classic templates in Java, that is, Servlet. The HttpService class provides a service() method, which calls one or more of the seven do methods to complete the response to the client call. These do methods need to be provided by the HttpServlet, and the details are provided by subclasses.
Template mode is mainly composed of abstract template role and concrete template role.
-
Abstract template: defines one or more abstract operations for subclasses to implement. These abstract operations are called basic operations, which are the constituent steps of a top-level logic; A template method is defined and implemented. This template method is generally a concrete method, which gives a skeleton of top-level logic, and the composition steps of logic are postponed to the implementation of subclasses in the corresponding abstract operations. It is also possible for top-level logic to call some specific methods.
-
Concrete template: implement one or more abstract methods defined by the parent class, which are the constituent steps of a top-level logic; Each abstract template role can have any number of concrete template roles corresponding to it, and each concrete template role can give different implementations of these abstract methods (that is, the composition steps of top-level logic), so that the implementations of top-level logic are different.
The example diagram is as follows:
For ease of understanding, we still use a simple example to illustrate.
In the past, when we played soul duel, double dragon, hot blood story, Ninja Turtle and other games, we need to insert a card on the little overlord game console, and then start the game to play. Among them, soul duel can be played directly after starting the game, but Ninja Turtle needs to select one of the characters to start playing after starting the game. Then we can write a general template according to this scene, which mainly includes several methods that must be realized, such as starting the game, playing the game and ending the game. The method of selecting characters is changed to optional.
The code of this abstract class is as follows:
abstract class Game{ //start games protected abstract void runGame(); //Select character protected void choosePerson() {}; //Start playing games protected abstract void startPlayGame(); //End the game protected abstract void endPlayGame(); //Template method public final void play() { runGame(); choosePerson(); startPlayGame(); endPlayGame(); } }
After defining the abstract class, we can define the concrete template implementation class. There are two game categories defined here, one is soul duel and the other is ninja turtle.
Then the code is as follows:
class ContraGame extends Game{ @Override protected void runGame() { System.out.println("Start soul duel II..."); } @Override protected void startPlayGame() { System.out.println("1P In use S Play and hit aircraft..."); } @Override protected void endPlayGame() { System.out.println("1P Killed by stray bullets, the game is over!"); } } class TMNTGame extends Game{ @Override protected void runGame() { System.out.println("Start Ninja Turtle III..."); } @Override protected void choosePerson() { System.out.println("1P Yes Raph !"); } @Override protected void startPlayGame() { System.out.println("Raph Using the stunt "rocket hammer" "); } @Override protected void endPlayGame() { System.out.println("Raph Fell into the manhole cover and died. The game is over! "); } }
Finally, the test code is as follows:
public static void main(String[] args) { Game game = new ContraGame(); game.play(); System.out.println(); game = new TMNTGame(); game.play(); }
Output result:
Start soul duel II... 1P In use S Play and hit aircraft... 1P Killed by stray bullets, the game is over! Start Ninja Turtle III... 1P Yes Raph ! Raph Using the stunt "rocket hammer" Raph Fell into the manhole cover and died. The game is over!
Advantages of template mode:
Good expansibility, encapsulating the unchanged code and expanding the variable code;
Good maintainability, because the public code is extracted and can be called directly when used;
Disadvantages of template mode:
Because each different implementation needs a subclass to implement, which will increase the number of classes and make the system complex;
Usage scenario:
Multiple subclasses share the same logical methods;
Important and complex methods can be considered as template methods.
matters needing attention:
In order to prevent malicious operations, the general template method adds the final keyword!