preface

In the daily Coding process, there are three design patterns: template, builder, strategy. Today, the third strategy design pattern is described

The policy mode is relatively simple and widely used. Usually, we use the policy mode to eliminate if-else, switch and other multiple judgment codes. Eliminating the if-else, switch and other multiple judgment can effectively deal with the complexity of the code

If the branch judgment is constantly changing (add, delete, change), then you can use other tricks to make it meet the open and close principle to increase the extensibility of the code (policy pattern scenarios are mainly responsible for decoupling, and the open and close principle requires additional support)

The following sections will detail how to use design patterns for a Demo, real-world scenarios of patterns, and the benefits of strategic patterns

The strategic design pattern is outlined below:

  1. What are strategic patterns
  2. Real world application scenarios in Spring projects
  3. How does the underlying framework source code play with the strategy pattern
  4. Summary of strategy Pattern

What are strategic patterns

Strategic patterns are defined in GoF’s Book Design Patterns as follows:

Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

Define a set of algorithm classes and encapsulate each algorithm individually so that they can be replaced with each other. The policy pattern enables these algorithms to change without affecting each other when a client calls them, meaning the code that uses the algorithm

It may not be clear what the policy pattern is, but I will start with the most basic code and thoroughly understand the pattern step by step. The following code may be associated with the corresponding business, according to the corresponding type of discount, the price of the corresponding discount

This code meets the business requirements of the project, and much of the code that goes live in production also has this code. However, there are two drawbacks to this code

  1. The complexity of the code, the normal business code logic is bound to be much more complex than this code block, which leads to if-else branching and too much code. This can be done by splitting the code into separate functions or classes
  2. On – off principle, price concessions will certainly change differently with different periods, perhaps new, deleted or modified. If making changes in a single function is scary, consider the possibility of multiple developers working separately, messy comments, messy code logic, and more

How can I use the strategy pattern to optimize the above code so that the program design looks simple and extensible

  1. To simplify the complexity of the code, different preferential types are defined as different strategy algorithm implementation classes
  2. Ensure open and close principle, increase the robustness and scalability of the program

Policy Pattern Example

Transforming the above code block into a policy design pattern takes roughly three steps

  1. Define abstract policy interfaces, because businesses use interfaces rather than concrete implementation classes, and have the flexibility to replace different policies
  2. The concrete policy implementation class is defined to realize the self-abstract policy interface and encapsulate the concrete business implementation internally
  3. Define policy factories, encapsulate creation policy implementations (algorithms), and shield clients from creation details

Now that we have created the abstract policy interface, the concrete policy implementation class, and the policy factory, we can take a look at how the client needs to be invoked, and how to shield the implementation details from the client

According to the code block image, the concrete policy class is retrieved from the policy factory, which does remove the if-else design and uses Map to store the policy implementation in the factory. After obtaining the policy class, execute the specific preferential policy method to obtain the amount after the preferential

Through analysis, you can see that the current design does reduce the complexity of the application code. If you add a preferential policy, you only need to add a policy algorithm implementation class. However, adding a policy algorithm implementation means changing the code in the policy factory, which still does not match the on/off principle

How to fully implement the policy pattern in accordance with the open and closed principle, with the help of Spring, please continue to see the detailed case

Real application scenarios in the project

A function designed in the recent project uses the policy mode, which is divided into two roles. The author is responsible for defining the abstract policy interface and policy factory. Different policy algorithms need to be implemented by various business parties, which can be associated with the coupon function mentioned above. Because it is a Spring project, it is processed in accordance with the Spring way, without further ado, on the code

You can see two obvious changes from the example code above

  1. In the abstract policy interface, a new mark() interface is defined to mark the uniqueness of the algorithm
  2. Concrete policy implementation classes, decorated with @Component, leave the objects themselves to Spring to manage

Tip: For ease of reading, mark() returns a string instead of a string. Readers are advised to use enumeration definitions when returning tokens

How can the abstract policy factory be modified to meet the open and close principle

It is the same as the previous responsibility chain mode (TODO adds link). The corresponding policy implementation is searched by calling IOC container in InitializingBean interface implementation, and then the return value of policy implementation mark() method is used as key. The policy implementation itself is added as a value to the Map container for the client to invoke

The SpringBoot test class used here injects the policy factory Bean, selects the specific strategy algorithm class through the policy factory, and then obtains the preferential price through the algorithm. Interlude: If you don’t want to inject a policy factory into Spring, there are many ways to do it

To summarize this section, we have optimized the code block at the beginning of this article in two ways through the strategy design pattern in combination with Spring: to deal with the complexity of the code and make it meet the open and closed principle. More specifically, by abstracting the policy algorithm class to reduce the complexity of the code, and then meeting the open and closed principle through some Spring features, now there is a new requirement to add a new policy class, robust and easy to expand

How does the source code base play the strategic pattern

It’s not enough to use for yourself. If necessary, you have to see how the people who design the open source framework source code apply the strategic pattern in their code

In the author’s understanding, JDK, Spring, SpringMvc, Mybatis, Dubbo and so on all use the strategy design pattern, here to Mybatis for example

Mybatis Executor stands for Executor, which is responsible for adding, deleting, modifying, and checking specific operations. There are two design patterns used, the template approach and the policy pattern

Executor represents the abstract policy interface, and the template method pattern I just described is derived from BaseExecutor

Configuration represents the policy factory and is responsible for creating specific policy algorithm implementation classes

SimpleExecuto, ReuseExecutor… Represents a class that encapsulates a specific strategy algorithm implementation

The above code block takes place in the Configuration class to create the Executor, which creates different strategy algorithms based on executorType judgment.

The code block above does not eliminate if-else completely, because the executer policy in Mybatis is basically fixed, which means that it only has these if-else judgments and is rarely added or modified. If you want to get rid of if-else, you can do it this way, so let me write some pseudo-code here

This approach, called “table lookup”, eliminates if-else branches through policy factory implementations. Finally, Mybatis is too detailed design here is no longer described, interested partners can go to download the source to chew a chew

If you add a new policy class, wouldn’t it still violate the open and close principle?

Yes, there is no way to implement the open close principle with the help of the IOC container, since Mybatis itself does not introduce Spring dependencies. Spring is an open closed principle solution. Is there another solution?

There are many solutions, the core of the open and closed principle is to close the original code modification, open to new code. You can scan for custom annotations under a specified package or use instanceof to determine whether it inherits from an interface. However, if the project uses Spring, it will be quiet

“Said

The article introduces the strategy mode with pictures and pictures, and then quotes the key point of this article: strategy design mode through the scene of price concessions. I believe that partners will have certain harvest after reading it

The essence of policy patterns is still to decouple code design through three roles: abstract policy interfaces, policy factories, and concrete policy implementation classes. The fine-grained policy implementation class avoids excessive body code and reduces design complexity

The author has heard many friends think that what they do is CRUD work, which is not challenging and boring. In fact, WHAT I’m trying to say is that business code is just as good as the programmer. It doesn’t have to be high concurrency, big data, etc. Quite a house does not sweep why sweep the world meaning

Finally, a question is raised: if-else code occurs, must we use policy pattern optimization

If if-else determines that branches are few and fixed, and no new branches will follow, then we can completely reduce the complexity of the program by pumping functions; Don’t try to get rid of if-else statements. Furthermore, using the policy pattern leads to an increase in classes, and there is no need to introduce the policy pattern for a small number of decision branches

This article is about the strategy design pattern here, will output factory, prototype, share and other modes; If the article is helpful to you, then point a concern to support it, wish you all the best.

Refer to the article

  • The Beauty of Design Patterns: Strategic Patterns

Wechat search [source interest circle], pay attention to the public number after reply 123 receive content covers GO, Netty, Seata, SpringCloud Alibaba, development specifications, interview treasure book, data structure and other learning materials!