java design mode -- strategy mode, payment method of handwritten mobile phone

Keywords: JDK Mobile Spring

Strategy mode

It defines the algorithm family and encapsulates them separately so that they can replace each other. This mode makes the change of algorithm not affect the users who use the algorithm.

Multiple if...else.. and switch statements can be avoided

 

Application scenario

1. If there are many classes in the system, and their differences only lie in their different behaviors.

2. A system needs to choose one of several algorithms dynamically.

For example, Jingdong now needs to promote sales and several preferential activities, so we can use the strategic model to write.

/**
 * @Author Darker
 * @Descrption Jingdong promotional activity preferential mode interface
 * @Date : Created in 13:54 2020-3-12
 */
public interface JDactivity {

    //Promotion method
    /**
     * 1.Original price
     * 2.Cash return
     * 3.Coupon reduction
     * 4.Gift in kind
     *
     */
    void activity();
}

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 13:57 2020-3-12
 */
public class EmptyActivity implements JDactivity{
    @Override
    public void activity() {
        System.out.println("Original price");
    }
}

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 13:59 2020-3-12
 */
public class CashBackActivity implements JDactivity{
    @Override
    public void activity() {
        System.out.println("Return cash directly for shopping and return cash to JD account");
    }
}

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 13:57 2020-3-12
 */
public class CouponsActivity implements JDactivity{
    @Override
    public void activity() {
        System.out.println("Collect coupons and reduce the price of shopping");
    }
}

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 14:00 2020-3-12
 */
public class GiftActivity implements JDactivity {
    @Override
    public void activity() {
        System.out.println("Shopping gifts");
    }
}

/**
 * @Author Darker
 * @Descrption Activity policy rules
 * @Date : Created in 14:02 2020-3-12
 */
public class ActivityStrategy {

    //Regarding preferential activities as member variables, which seed of new is which kind of preferential
    JDactivity jDactivity;

    public ActivityStrategy(JDactivity jDactivity){
        this.jDactivity = jDactivity;
    }

    public void execute(){
        jDactivity.activity();
    }
}


Run and try

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 14:04 2020-3-12
 */
public class StrategyTest {
    public static void main(String[] args) {
        //6.18 shopping activities
        ActivityStrategy activity618 = new ActivityStrategy(new CashBackActivity());
        activity618.execute();
        //Double 11 shopping discount
        ActivityStrategy activity1111 = new ActivityStrategy(new CouponsActivity());
        activity1111.execute();
    }
}

This is the application of the simplest strategy mode. It defines an algorithm family (preference family), and dynamically selects an algorithm (preference).

But! But! But!!!

At the user call layer, you will find that you want if...else; For example, here's how to generate the preferential activities you want through the fields sent from the front end. Since the policy mode avoids if...esle.., it's still used now. Of course, it's not allowed to play and combine. If you see the following code, you can get rid of a simple factory mode. We can completely change it to a factory mode and use the factory to generate this strategy. By the way, we can change the factory to a factory mode Single case, but also improve efficiency.

So, let's code him

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 14:40 2020-3-12
 */
public  class ActivityStrategyFactory {

    //Constructor privatization
    private  ActivityStrategyFactory(){};

    //A single case of starving Han style
    private static ActivityStrategyFactory activityStrategyFactory = new ActivityStrategyFactory();

    private static Map<String,JDactivity> iocMap = new HashMap<>();

    static {
        iocMap.put(ActivityKey.COUPON,new CouponsActivity());
        iocMap.put(ActivityKey.CASHBACK,new CashBackActivity());
        iocMap.put(ActivityKey.GIFT,new GiftActivity());
    }

    //No discount
    private static final ActivityStrategy  NON_ACTIVITY_STRATEGY = new ActivityStrategy(new EmptyActivity());

    //The only factory crossing in the whole world
    public static ActivityStrategyFactory getInstance(){
        return activityStrategyFactory;
    }

    //Activities for the factory to generate corresponding policies
    public ActivityStrategy getActivityStrategy(String activity){
        ActivityStrategy activityStrategy = new ActivityStrategy(iocMap.get(activity));
        return activityStrategy == null ? NON_ACTIVITY_STRATEGY:activityStrategy;
    }

    //Activity string, conventions > configuration
    private interface ActivityKey{
        String COUPON = "COUPON";
        String CASHBACK = "CASHBACK";
        String GIFT = "GIFT";
    }
}

Run it

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 14:04 2020-3-12
 */
public class StrategyTest {
    public static void main(String[] args) {

        //Active key from the front end
        String activityKey = "CASHBACK";
        //Generate policy factory
        ActivityStrategyFactory strategyFactory = ActivityStrategyFactory.getInstance();
        ActivityStrategy activityStrategy = strategyFactory.getActivityStrategy(activityKey);
        activityStrategy.execute();

    }
}

You see it's very friendly to client calls. No, when we add activities, we just need to add a little configuration field. It's also fast to change.

Let's take a look at this class diagram:

So it's clear that we have four preferential strategies, which are generated by activity strategies and produced by factories.  

Isn't it addictive? Let's recreate a function often used in daily life, mobile payment, a very classic strategy mode.

/**
 * @Author Darker
 * @Descrption Payment abstract class, including public judgment logic
 * @Date : Created in 16:12 2020-3-12
 */
public abstract class Paymet {

    public  abstract String getKeyName();

    //Check the balance
    protected abstract double queryBalance(String uid);

    //Public payment logic
    public MsgResult pay(String uid,double amount){
        if(queryBalance(uid)<amount){
            return new MsgResult(500,"Failure to pay","Sorry, your credit is running low");
        }else{
            return new MsgResult(200,"Successful payment","Payment amount"+amount);
        }
    }
}

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 16:11 2020-3-12
 */
public class Alipay extends Paymet{
    @Override
    public String getKeyName() {
        return "Alipay";
    }

    @Override
    protected double queryBalance(String uid) {
        return 250;
    }
}

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 16:16 2020-3-12
 */
public class JDpay extends Paymet {
    @Override
    public String getKeyName() {
        return "Jingdong ious";
    }

    @Override
    protected double queryBalance(String uid) {
        return 500;
    }
}

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 16:18 2020-3-12
 */
public class WechatPay extends Paymet {
    @Override
    public String getKeyName() {
        return "WeChat payment";
    }

    @Override
    protected double queryBalance(String uid) {
        return 700;
    }
}

/**
 * @Author Darker
 * @Descrption Order
 * @Date : Created in 15:45 2020-3-12
 */
@Data
@AllArgsConstructor
public class Order {
    private String uid;
    private String orderId;
    private Double amount;

    public MsgResult pay(String payKey){
        Paymet paymet = PayStrategy.getInstance(payKey);
        MsgResult result = paymet.pay(orderId, amount);
        return result;
    }

}

/**
 * @Author Darker
 * @Descrption Return package class
 * @Date : Created in 16:07 2020-3-12
 */
@Data
@AllArgsConstructor
public class MsgResult {

    private int code;
    private Object data;
    private String msg;

    @Override
    public String toString() {
        return "Payment status:[" + code +"]," + msg +",transaction details"+ data;
    }
}


/**
 * @Author Darker
 * @Descrption Payment strategy
 * @Date : Created in 16:25 2020-3-12
 */
public class PayStrategy {
    public static final String ALI_PAY = "Alipay";
    public static final String JD_PAY = "Jdpay";
    public static final String WECHAT_PAY = "Wechatpay";
    public static final String DEFAULT_PAY = ALI_PAY;

    private static Map<String, Paymet> payStrategy =new HashMap<>();

    static {
        payStrategy.put(ALI_PAY,new Alipay());
        payStrategy.put(JD_PAY,new JDpay());
        payStrategy.put(WECHAT_PAY,new WechatPay());
    }

    public static Paymet getInstance(String payKey){
        Paymet paymet = payStrategy.get(payKey) ;
        return paymet == null ? payStrategy.get(DEFAULT_PAY):paymet;
    }
}


/**
 * @Author Darker
 * @Descrption test
 * @Date : Created in 16:21 2020-3-12
 */
public class payStrategyTest {
    public static void main(String[] args) {
        String payKey = "Jdpay";
        String payKey2 = "Wechatpay";
        
        //User submitted an order
        Order order = new Order("1", "2020031200000000", 570.00);

        //User chooses payment method, Jingdong Baitiao
        MsgResult result = order.pay(payKey);
        System.out.println(result);

        //Payment method selected by users, wechat payment
        MsgResult result2 = order.pay(payKey2);
        System.out.println(result2);
    }
}

 

Let's see if this is the way we actually pay.

OK, finally, let's talk about where jdk uses the strategy mode. The answer is Comparator, Comparator. We often use Comparator to sort. There are many algorithms in this Comparator. We can choose our own preferred strategy to sort, which is very classic.

 

Similarly, the policy pattern is also used in spring. When initializing a class, it will choose whether to use jdk or cglib.

 

 

Conclusion:

Advantage:

1. The strategy mode conforms to the opening and closing principle

2. Avoid using multiple conditional transfer statements, such as if...else

3. Using policy mode can improve the security and secrecy of the algorithm

Disadvantages:

1. The client must know all policies and decide which policy class to use.

2. A lot of policy classes will be generated in the code. Do you want to add maintenance.

Published 23 original articles, won praise 1, visited 3582
Private letter follow

Posted by maltech on Thu, 12 Mar 2020 03:03:03 -0700