This is the 22nd day of my participation in the August Wen Challenge.More challenges in August

Today weekend, tomorrow Monday, also can be regarded as a time node, this month’s unfinished design mode, finally with a familiar and commonly used mode to make a conclusion. There are strategic patterns all over the web, but this article is based on solving real problems.

Q: What design patterns have you used in your work

A: Strategic mode, or strategic mode

Today I will use the most real case to apply, so that you in the future in the process of work 100 not happy!

The strategy pattern

The official definition is to define a series of algorithms, encapsulate each algorithm, and make them interchangeable. A policy lets the algorithm change independently of the client that uses it.

As usual we first look at the diagram, explain, finally code drill!!

Let’s look at the second image below:

From this figure, we can see that the policy pattern contains three key actors

  • Context information classes: Used to hold and execute the specific policy classes that need to be used and the logic that the client calls

  • Abstract Policy class (Strategy) : Defines the common methods of policies, functions that all policies have in common

  • Concrete policy classes (StrategyA, etc.) : Common methods that implement abstract policy class definitions.

Note here, the policy class, can only have one class (generally interface), the specific policy class is multiple, there are several policies as many policy classes.

Let’s start with a simple piece of code (for those of you who don’t know the policy pattern)

Code demo

// Context information class
// Logical for storing and executing specific policy classes and client calls that need to be used
public class Context {
    
    public void request(Strategy s) { s.operation(); }}// Policy interface
// Define common methods for the policy
public interface Strategy {
    void operation(a);
}


// Concrete policy class A implements the policy class
public class StrategyA implements Strategy {
    @Override
    public void operation(a) {
        System.out.println("=== Execute policy A......"); }}// Concrete policy class B implements the policy class
public class StrategyB implements Strategy {
    @Override
    public void operation(a) {
        System.out.println("=== Execute policy B......"); }}Copy the code

From the above code implementation, we can see that the essence of the policy pattern is to schedule and allocate different policies through the context information class as the central control unit.

Let’s take a look at the actual scenario, the most likely scenario is the marketing scenario.

Now I want to be a platform member. Platform membership is mainly about rights and interests. For example, if I buy a platform membership, I will have the following rights and interests

1. Free platform coupons

2. Complimentary admission ticket

3. Bonus points

.

So these can be thought of as strategies, and our strategies, in my opinion, fall into two broad categories

  • Specify the policy. I specify a policy pattern for each request, such as our sharing feature. You can only share one at a time

  • The whole strategy. As for the membership rights and interests mentioned above, after users purchase platform members, they have to send these rights and interests to users.

Let’s first take the platform membership scene to demonstrate (this case is a real case, please see the end of remember to like the collection) :

First, let’s define the policy API — the PlatformApi — that each algorithm of the membership equity policy implements. This interface has a getPlatformType method that receives and returns a member equity type of type byte. Another createPlatformUser sends membership benefits.


/** * Platform member rights API *@Date 2021/08/22 4:09 下午
 * @Author yn
 */
public interface IPlatformAPI {
    
    
    /** * Rights and interests * 1, free platform coupons * 2, free movie tickets * 3, free points * 4, free video members * 5, cooperation with Meituan, free Meituan members *@return* /
    byte getPlatformType(a);



    /** * Create platform member user rights (send rights) *@paramUserId to whom to send membership benefits *@return* /
    void createPlatformUser(Integer userId);
}
Copy the code

Next we define the policy implementation class.

/** ** Send coupons *@Date 2021/08/22 6:05 下午
 * @Author yn
 */
@Service
public class PlatformCouponAPI implements IPlatformAPI {

    
    @Override
    public byte getPlatformType(a) {
        // Free platform membership
        return 1;
    }
    
    
    @Override
    public void createPlatformUser(Integer userId) {
        // Execute the logic of sending coupons}}/** ** Movie tickets *@Date 2021/08/22 6:05 下午
 * @Author yn
 */
@Service
public class PlatformMmovieCouponAPI implements IPlatformAPI {

    
    @Override
    public byte getPlatformType(a) {
        // Send tickets
        return 2;
    }
    
    
    @Override
    public void createPlatformUser(Integer userId) {
        // Execute the logic to send tickets}}/** * free credits *@Date 2021/08/22 6:05 下午
 * @Author yn
 */
@Service
public class PlatformIntegralAPI implements IPlatformAPI {

    
    @Override
    public byte getPlatformType(a) {
        // Free credits
        return 3;
    }
    
    
    @Override
    public void createPlatformUser(Integer userId) {
        // Execute the logic of gifting credits}}Copy the code

After the user has made the purchase, we send the user the equity



/** *@Date 2021/08/22 4:50 下午
 * @Author yn
 */
@Service
public  class PlatformAPI {

    @Autowired
    private IPlatformAPI api;

    public void sendPlatformCard(a){
        api.createPlatformUser(12345); }}// You can see that the above method does not work.

// If the type is not specified, how to find the specified bean (policy execution class)
// There is an important question: how do I get Spring to scan the specified Bean by type
// 3 We all know that Spring can scan in our Controller because of @service

// 4 Here we force the scan bean in a different way, dynamic invocation
Copy the code

First define a PlatformStrategy policy set class, so that the business type and class are loaded into the map, one by one mapping. When we go to load the bean. I take it straight from here


/** * Policy set class *@Date 2021/08/22 3:47 下午
 * @Author yn
 */
public class PlatformStrategy {

    // ConcurrentHashMap is used here to prevent unpredictable errors caused by concurrency
    private static Map<Byte, IPlatformAPI> map = new ConcurrentHashMap<>(16);

    / / type
    public IPlatformAPI getPlatformStrategy(byte type) {
        return map.get(type);
    }

    // Insert the type and class
    public IPlatformAPI setPlatformStrategy(byte type, IPlatformAPI iPlatformAPI) {
        returnmap.put(type, iPlatformAPI); }}Copy the code

So at this point we’re thinking, well, PlatformStrategy class doesn’t have anything that Spring can scan into and how can we call it. Don’t panic. Look at the following


// We all know. Adding these two annotations directly initializes the bean
As a Configuration class, @configuration
// Component @Component
@Component
@Configuration
public class PlatformStrategyConfiguration {


    @Bean // Bean annotations must be added
    public PlatformStrategy setStrategyList(List<IPlatformAPI> iPlatformAPIS) {
        //iPlatformAPIS All policy implementation classes
        PlatformStrategy platformStrategy = new PlatformStrategy();
        
        // Put all the classes in
        iPlatformAPIS.forEach(iPlatformAPI -> {
            platformStrategy.setPlatformStrategy(iPlatformAPI.getPlatformType(), iPlatformAPI);
        });
        returnplatformStrategy; }}Copy the code

OK. At this point our low-level configuration work is complete, we will modify the above error code


// simulate the call
@Service
public  class PlatformAPI {

    // Import the set policy class
    @Autowired
    private PlatformStrategy platformStrategy;

    
    /** * sends equity by type call *@paramList Sets of types *@paramUserId To whom the user sends the rights */
    public void sendPlatformCard(List<ThsPlatFormCardConfigInfo> list, Integer userId){
        
        // Send in a loop
        list.forEach(s ->{
        
            // Check beans by rights (policy class)
            IPlatformAPI iPlatformAPI = platformStrategy.getPlatformStrategy(s.getCardType());
            
            // Actually call sendiPlatformAPI.createPlatformUser(userId); }); }}Copy the code

Here pay attention to the parameters of the code above we List < ThsPlatFormCardConfigInfo > List here is ok according to the database configuration, such as our rapid shelves today we are going to a rights and interests. Then you can configure it directly according to the database. No code to do that.

That’s where the OK code ends

Here’s a summary of today’s strategy patterns

conclusion

We briefly summarize the advantages of the strategic mode, and today’s focus is the application of this strategic mode above us.

  • First, improve code maintainability and provide good code extensibility. In the actual development, there are many algorithms that can achieve a certain function, such as search, sort, etc. It is very convenient to select by if-else and other conditional judgment statements

  • Second, in order to dynamically replace more algorithms quickly. As you can see from the above analysis, the greatest power of the policy pattern lies in separating the logic that uses the algorithm from the logic that the algorithm itself implements

  • Third, to deal with scenarios that require frequent policy changes. Like the equity allocation table we talked about above

  • Reduce the difficulty of understanding statements nested with multiple conditions (if-else)

Policy patterns are most useful for changing the algorithmic behavior of code at run time, while giving consumers a way to choose algorithms based on the situation.

overtones

Design patterns are over for today, and I will continue to output other columns. Thank you for reading, if you feel that you have learned something, please like, follow.

I have included this chapter in the features section. Click on the features below to follow the column.

I’ll post another practice using multiple design patterns later.

Come on! See you next time!

History of dry

Singletons of design patterns

Factory patterns for design patterns

The Builder pattern of design patterns

Proxy patterns for design patterns

Visitor patterns for design patterns

Adapter pattern for design pattern

Design pattern of the command pattern

Java state pattern | monitoring state change anytime and anywhere

Java observer pattern | how to notice things change

Java mode | how to record history information memorandum

Java iterator pattern model | how to access each element

Java the flyweight pattern | how to share the object

Java interpreter pattern | custom rules implementation logic

The Java bridge model | abstract binding with different implementations

Look! Here comes the chain of responsibility model