打赏
Fork me on GitHub

策略模式

策略模式:

  策略模式(Strategy Pattern)是指定义了算法家族并分别封装起来,让他们之间可以互相替换,此模式使用得算法的变化不会影响使用算法的用户。

应用场景:

  (1)系统中有很多类,而他们的区别仅仅在于行为不同。

  (2)一个系统需要动态地在几种算法中选择一种。

  例如:大家都用过支付宝支付、微信支付、银联支付、以及京东白条支付。一个常见的应用场景就是大家在支付时会提示选择支付方式,如果用户未选择,系统会使用默认的支付方式进行结算。

  使用策略模式模拟次业务场景。

  创建 Payment 抽象类,定义支付规范和支付逻辑:

package com.xq.design.startegy.pay.payport;

import com.xq.design.startegy.pay.PayState;

public abstract class Payment {

    //支付类型
    public abstract String getName();

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

    //扣款支付
    public PayState pay(String uid, double amount){
        if(queryBalance(uid) < amount){
            return new PayState(500,"支付失败","余额不足");
        }
        return new PayState(200,"支付成功","支付金额:" + amount);
    }
}

  分别创建具体的支付方式,支付宝支付类 AliPay:

package com.xq.design.startegy.pay;

import com.xq.design.startegy.pay.payport.Payment;

public class AliPay extends Payment {
    @Override
    public String getName() {
        return "支付宝";
    }

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

  银联支付类 UnionPay :

package com.xq.design.startegy.pay;

import com.xq.design.startegy.pay.payport.Payment;

public class UnionPay extends Payment {
    @Override
    public String getName() {
        return "银联支付";
    }

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

  京东白条支付类 JDPay:

package com.xq.design.startegy.pay;

import com.xq.design.startegy.pay.payport.Payment;

public class JDPay extends Payment {
    @Override
    public String getName() {
        return "京东白条";
    }

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

  创建支付状态的包装类 PayState:

package com.xq.design.startegy.pay;

public class PayState {
    private int code;
    private Object data;
    private String msg;

    public PayState(int code, String msg, Object data){
        this.code = code;
        this.data = data;
        this.msg =msg;
    }

    public String toString(){
        return ("支付状态:【" + code +"】," + msg + ",交易详情:" + data);
    }
}

  创建支付策略管理类 PayStrategy:

package com.xq.design.startegy.pay.payport;

import com.xq.design.startegy.pay.AliPay;
import com.xq.design.startegy.pay.JDPay;
import com.xq.design.startegy.pay.UnionPay;
import com.xq.design.startegy.pay.WechatPay;

import java.util.HashMap;
import java.util.Map;

public class PayStrategy {
    public static final String ALI_PAUY = "AliPay";
    public static final String JD_PAY = "jdPay";
    public static final String UNION_PAY = "UnionPay";
    public static final String WECHAT_PAY = "WechatPay";
    public static final String DEFAULT_PAY = ALI_PAY;

    private static Map<String,Payment> payStrategy = new HashMap<String,Payment>();
    static{
        payStrategy.put(ALI_PAY, new AliPay());
        payStrategy.put(WECHAT_PAY, new WechatPay());
        payStrategy.put(UNION_PAY, new UnionPay());
        payStrategy.put(JD_PAY, new JDPay());
    }
    public static Payment get(String payKey){
        if(!payStrategy.containsKey(payKey)){
            return payStrategy.get(payKey);
        }
        return payStrategy.get(payKey);
    }
}

  创建订单类 Order:

package com.xq.design.startegy.pay;

import com.xq.design.startegy.pay.payport.PayStrategy;
import com.xq.design.startegy.pay.payport.Payment;

public class Order {
    private String uid;
    private String orderId;
    private double amount;

    public Order(String uid, String orderId, double amount) {
        this.uid = uid;
        this.orderId = orderId;
        this.amount = amount;
    }
    //完美的解决了 switch 过程,不需要再代码中写switch了,更不需要写 if ... else if
    public PayState pay(){
        return  pay(PayStrategy.DEFAULT_PAY);
    }

    public PayState pay(String paykKey) {
        Payment payment = PayStrategy.get(paykKey);
        System.out.println("欢迎使用" + payment.getName());
        System.out.println("本次交易金额为:" + amount + ",开始扣款...");
        return payment.pay(uid,amount);
    }
}

  测试代码如下:

package com.xq.design.startegy.pay;

import com.xq.design.startegy.pay.payport.PayStrategy;

public class PayStrategyTest {
    public static void main(String[] args) {
        Order order = new Order("1","202005130000001",326.5);
        /**
         * 开始支付,选择支付方式
         * 每个渠道支付的具体算法是不一样的,基本算法是固定的
         * 在支付的时候才决定这个值是用哪个
         */
        System.out.println(order.pay(PayStrategy.ALI_PAY));
    }
}

  结果如下:

 策略模式的优缺点

  策略模式有点如下:

  (1)策略模式符合开闭原则。  

  (2)策略模式可避免使用多重条件语句,如 if...else 语句、switch语句。

  (3)使用策略模式可以提高算法的保密性和安全性。

  策略模式的缺点如下:

  (1)客户端必须知道所有的策略,并且自行决定使用哪一个策略类。

  (2)代码中会产生非常多的策略类,增加了代码的维护难度。

 

posted @ 2020-05-13 22:43  l-coil  阅读(175)  评论(0编辑  收藏  举报