Stop playing if and else on the full screen. Try the strategy mode. It's really fragrant!!

Are you still writing judgment logic like if/ else/ switch full screen?

The stack leader has seen too many such low-level codes in the developer's code. They are really too low and very difficult to maintain. In this paper, the stack leader will teach you how to kill if/ else/ switch with policy mode to make your code more elegant.

What is the strategy model?

For example, a behavior of an object has different implementation methods in different scenarios. In this way, these implementation methods can be defined as a group of policies. Each implementation class corresponds to a policy. Different implementation classes are used in different scenarios, and the policies can be switched freely.

The structure diagram of the strategy mode is as follows:

The policy mode requires a policy interface. Different policies implement different implementation classes. Only this policy interface is held in the specific business environment, and different implementation classes can be used according to different scenarios.

Interface oriented programming, not implementation oriented.

Advantages of policy mode:

1. Eliminate the tedious if and switch judgment logic;

2. The code is elegant, reusable and readable;

3. Comply with the opening and closing principle, with good expansibility and easy maintenance;

Disadvantages of policy mode:

1. If there are many policies, it will cause the expansion of policy class;

2. Users must be aware of all policy classes and their uses;

Strategy mode actual combat

A practical example is that XX company pays for the payment. According to different types of customers, there will be different payment methods and payment products, such as credit card and local payment, while local payment in China has more WeChat payment, Alipay, cloud flash payment and more other third party payment companies.

The traditional judgment writing methods such as if/ else/ switch can be written by everyone. There is no code posted here. It directly depends on the strategy mode!

1. Define policy interface

Define a policy interface, the interface of all payment methods.

Policy interface:

/**
 * Payment interface
 * @author: Stack length
 * @from: Official account Java technology stack
 */
public interface IPayment {

    /**
     * payment
     * @param order
     * @return
     */
    PayResult pay(Order order);

}

Order information:

/**
 * Order information
 * @author: Stack length
 * @from: Official account Java technology stack
 */
@Data
public class Order {

    /**
     * amount of money
     */
    private int amount;

    /**
     * Payment type
     */
    private String paymentType;

}

Return result class:

/**
 * @author: Stack length
 * @from: Official account Java technology stack
 */
@Data
@AllArgsConstructor
public class PayResult {

    /**
     * Payment results
     */
    private String result;

}

2. Define various policies

Various payment strategies are defined, such as WeChat payment, Alipay, cloud flash payment and other payment implementation classes.

Wechat payment implementation:

/**
 * Wechat payment
 * @author: Stack length
 * @from: Official account Java technology stack
 */
@Service("WechatPay")
public class WechatPay implements IPayment {

    @Override
    public PayResult pay(Order order) {
        return new PayResult("Wechat payment succeeded");
    }

}

Alipay achieves:

/**
 * Alipay
 * @author: Stack length
 * @from: Official account Java technology stack
 */
@Service("Alipay")
public class Alipay implements IPayment {

    @Override
    public PayResult pay(Order order) {
        return new PayResult("Alipay paid successfully");
    }

}

Cloud flash payment implementation:

/**
 * UnionPay cloud flash payment
 * @author: Stack length
 * @from: Official account Java technology stack
 */
@Service("UnionPay")
public class UnionPay implements IPayment {

    @Override
    public PayResult pay(Order order) {
        return new PayResult("Cloud flash payment succeeded");
    }

}

Here, I put all payment method classes into the Spring Bean container with the @ Service annotation. When using the policy, I don't need the new payment object. I can directly use the Bean, which is closer to the business. Spring basic tutorial is not introduced, you can pay attention to the official account Java technology stack, reply: spring, history tutorial I have arranged.

3. Use strategy

Some articles use enumeration and HashMap to map policy implementation classes according to policy names. This is no problem, but it is a bit superfluous in projects that use the Spring framework. We can give full play to the advantages of the Spring framework and use the Bean name to find the corresponding policy implementation classes.

The reference example code is as follows:

/**
 * Payment services
 * @author: Stack length
 * @from: Official account Java technology stack
 */
@RestController
public class PayService {

    @Autowired
    private ApplicationContext applicationContext;

    /**
     * Payment interface
     * @param amount
     * @param paymentType
     * @return
     */
    @RequestMapping("/pay")
    public PayResult pay(@RequestParam("amount") int amount,
                    @RequestParam("paymentType") String paymentType) {
        Order order = new Order();
        order.setAmount(amount);
        order.setPaymentType(paymentType);

        // Obtain the corresponding policy bean according to the payment type
        IPayment payment = applicationContext.getBean(order.getPaymentType(), IPayment.class);

        // Start payment
        PayResult payResult = payment.pay(order);

        return payResult;
    }

}

Looking at the sample code, I did not create a new Context class to hold the policy interface as in the policy pattern structure diagram. It is a standard policy pattern. In fact, the reason is the same. The key is how to implement the policy.

Test:

http://localhost:8080/pay?amount=8800&paymentType=WechatPay

Test OK. Different payment methods will call different strategies.

All the actual combat source code of this tutorial has been uploaded to this warehouse: https://github.com/javastacks/javastack

Application of policy pattern in JDK

Now that we know how to use the policy pattern, let's look at where the JDK uses the policy pattern.

1. Reject policy in thread pool

There is a reject policy parameter in the construction of thread pool. The default is the default reject policy:

In fact, this is a policy interface:

There are several implementations of rejection policies:

Creating Thread pool Different rejection policies can be passed in when the policy pattern is changed. This is the classic implementation of the policy pattern in JDK.

2. Comparator

The policy interface Comparator is widely used in JDK:

There is a policy interface, but the policy needs to be determined by the developers themselves.

We are familiar with collection sorting. Different sorting rules are actually different strategies:

This policy mode uses a functional programming interface, and the comparison rules can be done by using anonymous internal classes or Lambda expressions. There is no need to define an implementation class for each rule, so a large number of policy classes are omitted.

This policy pattern may be hidden deep, but it is also the application of the classic policy pattern in JDK.

Not limited to these two, in fact, there are more. Do you know anything else? Welcome to share

Therefore, the strategy model is right beside you. You have been using it all the time, but you may not notice it..

summary

Using the policy pattern, we can easily kill a large number of if/ else, and the code is more elegant and flexible.

Like the payment case in this article, we don't need to modify the existing code for how many payment methods we want to add or delete later, so it won't affect the existing business, and really open to expansion and close to modification.

Of course, it is impossible to kill if/ else completely. You can't over design and use design patterns for the purpose of using design patterns, otherwise it will backfire. However, every programmer needs to master the strategy mode and be flexible in the system, so as to write more elegant and high-quality code.

All the actual combat source code of this tutorial has been uploaded to this warehouse:

https://github.com/javastacks/javastack

OK, today's sharing is here. After the stack length, I will update other design patterns of actual combat articles, official account Java technology stack for the first time. The Java technology stack "design patterns" series of articles are being updated one after another. Please continue to pay attention!

Finally, I think if my article is useful to you, use your small hand to read and forward it. It's not easy to be original. The stack leader needs your encouragement.

Copyright declaration: This article is the official account "Java technology stack" original, original is not easy, reprint and quote the content of this article, please indicate the source, prohibit copying and washing manuscripts, please respect yourself, respect others' labor achievements and intellectual property rights.

Recent hot article recommendations:

1.600 + Java interview questions and answers (2021 latest edition)

2.Finally got the IntelliJ IDEA activation code through the open source project. It's really fragrant!

3.Ali Mock tools are officially open source and kill all Mock tools on the market!

4.Spring Cloud 2020.0.0 is officially released, a new and subversive version!

5.Java development manual (Songshan version) is the latest release. Download it quickly!

Feel good, don't forget to like + forward!

Added by Hardbyte on Wed, 09 Feb 2022 18:57:33 +0200