java design patterns ---- strategy pattern, handwriting mobile payment

Strategy Mode

Is the definition of a family of algorithms, encapsulate them, so that they can be replaced between each other, this mode allows changes in the algorithm does not affect the user algorithm.

Avoids multiple points of if ... else .. and switch statements

 

Scenarios

1. If the system has a lot of class, and they differ only in their behavior.

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

Example, Jingdong now engage in promotions, requires several promotions, we can use the strategy pattern to write.

/**
 * @Author Darker
 * @Descrption 京东促销活动优惠方式接口
 * @Date : Created in 13:54 2020-3-12
 */
public interface JDactivity {

    //促销方式
    /**
     * 1.原价
     * 2.现金返现
     * 3.优惠券减免
     * 4.赠送实物
     *
     */
    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("原价");
    }
}

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 13:59 2020-3-12
 */
public class CashBackActivity implements JDactivity{
    @Override
    public void activity() {
        System.out.println("购物直接返现,返回现金到京东账号");
    }
}

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 13:57 2020-3-12
 */
public class CouponsActivity implements JDactivity{
    @Override
    public void activity() {
        System.out.println("领取优惠券,购物减免价格");
    }
}

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

/**
 * @Author Darker
 * @Descrption 活动策略规则
 * @Date : Created in 14:02 2020-3-12
 */
public class ActivityStrategy {

    //把优惠活动作为成员变量,new哪一种子类就是哪一种优惠
    JDactivity jDactivity;

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

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


Try running

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 14:04 2020-3-12
 */
public class StrategyTest {
    public static void main(String[] args) {
        //6.18购物活动
        ActivityStrategy activity618 = new ActivityStrategy(new CashBackActivity());
        activity618.execute();
        //双11购物优惠
        ActivityStrategy activity1111 = new ActivityStrategy(new CouponsActivity());
        activity1111.execute();
    }
}

This is the easiest to use of the Strategy pattern defines a family of algorithms (family discount), select a dynamic algorithm (discount).

but! but! but! ! !

To the user call level, you will find that you have to if ... else ..; such as this, which you want to generate promotions came through the front of the field, since that strategy pattern to avoid if ... esle .., now do not still use the thing, of course, a play can not not binding, see the following code to look just like a simple factory pattern Well, we can change the factory pattern, with a factory to produce this strategy, the way to become factory single embodiment, but also to improve efficiency.

So, we gave him add the code

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

    //构造方法私有化
    private  ActivityStrategyFactory(){};

    //饿汉式单例
    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());
    }

    //无优惠
    private static final ActivityStrategy  NON_ACTIVITY_STRATEGY = new ActivityStrategy(new EmptyActivity());

    //全局唯一工厂路口
    public static ActivityStrategyFactory getInstance(){
        return activityStrategyFactory;
    }

    //工厂生成相应策略的活动
    public ActivityStrategy getActivityStrategy(String activity){
        ActivityStrategy activityStrategy = new ActivityStrategy(iocMap.get(activity));
        return activityStrategy == null ? NON_ACTIVITY_STRATEGY:activityStrategy;
    }

    //活动字符串,约定>配置
    private interface ActivityKey{
        String COUPON = "COUPON";
        String CASHBACK = "CASHBACK";
        String GIFT = "GIFT";
    }
}

 Look at the operation

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

        //前端传来的活动key
        String activityKey = "CASHBACK";
        //生成策略工厂
        ActivityStrategyFactory strategyFactory = ActivityStrategyFactory.getInstance();
        ActivityStrategy activityStrategy = strategyFactory.getActivityStrategy(activityKey);
        activityStrategy.execute();

    }
}

You look so very friendly to the client calls is not, but when we increased activity when simply going to add a little configuration fields on the line, change up soon.

We look at the class diagram:

This is very clear, we have four preferential policies to generate the corresponding policies through active policy, and with factories to produce strategies. 

Is not good enough, then we come to a recurring feature often used in everyday, mobile payment, a very classic strategy mode.

/**
 * @Author Darker
 * @Descrption 支付抽象类,包含公共判断逻辑
 * @Date : Created in 16:12 2020-3-12
 */
public abstract class Paymet {

    public  abstract String getKeyName();

    //查询余额
    protected abstract double queryBalance(String uid);

    //公用支付逻辑
    public MsgResult pay(String uid,double amount){
        if(queryBalance(uid)<amount){
            return new MsgResult(500,"支付失败","余额不足");
        }else{
            return new MsgResult(200,"支付成功","支付金额"+amount);
        }
    }
}

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

    @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 "京东白条";
    }

    @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 "微信支付";
    }

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

/**
 * @Author Darker
 * @Descrption 订单
 * @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 返回包装类
 * @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 "支付状态:[" + code +"]," + msg +",交易详情"+ data;
    }
}


/**
 * @Author Darker
 * @Descrption 支付策略
 * @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 测试
 * @Date : Created in 16:21 2020-3-12
 */
public class payStrategyTest {
    public static void main(String[] args) {
        String payKey = "Jdpay";
        String payKey2 = "Wechatpay";
        
        //用户提交了一个订单
        Order order = new Order("1", "2020031200000000", 570.00);

        //用户选择支付方式,京东白条
        MsgResult result = order.pay(payKey);
        System.out.println(result);

        //用户选择支付方式,微信支付
        MsgResult result2 = order.pay(payKey2);
        System.out.println(result2);
    }
}

 Take a look, this is not the way we actually pay to use it.

Well, finally, we come to talk about where jdk with the strategy pattern, the answer is the Comparator, Comparator, we often sort comparator, this comparator there are a lot of algorithms, we are free to choose their favorite strategies Sort, very classic.

Similarly, in the spring also used the strategy pattern in the initialization of the class when it is selected jdk way or cglib way.

 

to sum up:

advantage:

1. Strategy pattern in line with the principle of opening and closing

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

3. Use the Strategy pattern can improve the confidentiality and security of the algorithm

Disadvantages:

1. The client must know all the tactics and strategy to decide which class to use.

2. The code will generate a lot of strategy category, maintenance is more difficult.

Published 27 original articles · won praise 1 · views 3641

Guess you like

Origin blog.csdn.net/qq_40111437/article/details/104817532