Design Pattern: Policy Pattern (Java)
In policy mode, the behavior of a class or its internal algorithm can be changed at run time.
An overview of the
When a problem requires multiple approaches that differ only in specific behavior, we can abstract the differences as a unified interface. The consumer can then handle this problem at run time by choosing a different interface implementation, which can be understood as a policy. Using different strategies to solve the same or the same type of problem is called the strategy pattern.
For example, if we want to sort a set of data, we need to choose the sort strategy based on the actual scenario, such as insertion sort, merge sort, and bubble sort. For such requirements, we can abstract the sorting logic as an interface and then provide one or more implementations (policies) of that interface by default. At run time, the user can set the policy and perform the sorting as needed. If the default policy does not meet the requirements, the user can implement a new sorting policy based on the interface.
It’s a little abstract, right? So let’s draw a picture:
In the figure above, we want to match 2, 6, 2, 7, 9, 5… By default, insertion sort, merge sort and bubble sort are provided. When sorting, we can choose one of them to participate in the sorting logic. Of course, if we want to sort by another sort strategy, we can do it ourselves (such as implementing an exchange sort strategy).
The sample
Two lines of code are worth a thousand words.
Now let’s move on to the example: Design an algorithm that uses different strategies (addition, subtraction, multiplication, and division) to evaluate two numbers.
Code design
Public interface Strategy {int doOperation(int a, int b); } public implements Strategy {@override public int doOperation(int a, int b) {return a + b; }} // Policy: Public class implements Strategy {@override public int doOperation(int a, int b) {return a-b; }} // Policy: Public class MultiplyStrategy implements Strategy {@override public int doOperation(int a, int b) {return a * b; }} // Policy: Public class DivisionStrategy implements Strategy {@override public int doOperation(int a, int b) {return a/b; }}Copy the code
Public class Context {private int mA; private int mB; private Strategy mStrategy; public Context(int a, int b) { mA = a; mB = b; // The default strategy is "add" mStrategy = new AddStrategy(); } public int execute() { return mStrategy.doOperation(mA, mB); } public void setStrategy(Strategy strategy) { mStrategy = strategy; }}Copy the code
Code validation
Public static void main(String[] args) {Context Context = new Context(8, 5); public static void main(String[] args) {Context Context = new Context(8, 5); System.out.println(" + context.execute() "); context.setStrategy(new SubtractionStrategy()); System.out.println(" minus: "+ context.execute()); context.setStrategy(new DivisionStrategy()); System.out.println(" multiply: "+ context.execute()); context.setStrategy(new SubtractionStrategy()); System.out.println(" except: "+ context.execute()); }Copy the code
Plus: 13 minus: 3 times: 40 divided by: 1Copy the code
As can be seen from the above output logs, the calculation results of the same computing system are different after different computing strategies are set.
extension
Add, subtract, multiply, and divide are provided by default in the above operation system. Now we feel that this is not enough, and we want to define some other policies outside the system, such as “remainder” :
public class RemainStrategy implements Strategy { @Override public int doOperation(int a, int b) { return a % b; } } // context.setStrategy(new SubtractionStrategy()); // system.out.println (" I: "+ context.execute()); / / yu: 3Copy the code
conclusion
Advantages of policy mode:
- Algorithms can be switched freely.
- Avoid using multiple criteria for judgment.
- Good scalability.
Disadvantages of policy mode:
- Policy classes will increase.
- All policy classes need to be exposed.
Application scenarios of policy mode:
- When there are more than one type of problem that requires more than one way of dealing with it, and these ways of dealing with it differ only in behavior.
- When multiple operations of the same type need to be securely encapsulated.
- Multiple subclasses of the same abstract class occur and need to be used
if-else
或switch-case
To select a subclass.