一、定义

策略模式(Strategy Pattern) 又叫政策模式(Policy Pattern), 他是将定义的算法家族、分别封装起来, 让他们之间可以相互替换, 从而让算法的变化不会影响到使用算法的用户.

可以避免多重的 if...else...switch语句

属于行为型设计模式

二、意图:

定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

三、主要解决:

在有多种算法相似的情况下,使用 if...else、switch 等所带来的复杂和难以维护。

四、适用场景

  1. 假如系统中有很多类, 而他们的区别仅仅在于他们的行为不同.
  2. 一个系统需要动态的在几种算法中选择一种.
  3. 需要屏蔽算法规则.

五、Java代码简单案例

案例采用于生活中的支付场景. 生活中有 支付宝, 微信, 银联, 京东支付等..

1. 定义支付抽象类和实现类

/**
 * 1. 支付抽象类
 */
public abstract class Payment {

    public abstract String getName();

    //通用逻辑放到抽象类里面实现
    public MsgResult pay(String uid, double amount){
        //余额是否足够
        if(queryBalance(uid) < amount){
            return new MsgResult(500,"支付失败","余额不足");
        }
        return new MsgResult(200,"支付成功","支付金额" + amount);
    }
    
    // 由各自实现类自行实现
    protected abstract double queryBalance(String uid);
}
/**
 * 支付宝支付实现类
 */
public class AliPay extends Payment {
    public String getName() {
        return "支付宝";
    }

    // 支付宝查询余额方法
    protected double queryBalance(String uid) {
        return 900;
    }
}
/**
 * 京东支付实现类
 */
public class JDPay extends Payment {
    public String getName() {
        return "京东白条";
    }

    // 京东支付查询余额方法
    protected double queryBalance(String uid) {
        return 500;
    }
}
/**
 * 银联支付实现类
 */
public class UnionPay extends Payment {
    public String getName() {
        return "银联支付";
    }
    
    // 银联支付查询余额方法
    protected double queryBalance(String uid) {
        return 120;
    }
}
/**
 * 微信支付实现类
 */
public class WechatPay extends Payment {
    public String getName() {
        return "微信支付";
    }
    
    // 微信支付查询余额方法
    protected double queryBalance(String uid) {
        return 263;
    }
}

2. 定义支付策略类

/**
 * 2. 定义支付策略类
 */
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 UNION_PAY = "UnionPay";
    public static  final String DEFAULT_PAY = ALI_PAY;

    private static Map<String,Payment> strategy = new HashMap<String,Payment>();

    static {
        strategy.put(ALI_PAY,new AliPay());
        strategy.put(JD_PAY,new JDPay());
        strategy.put(WECHAT_PAY,new WechatPay());
        strategy.put(UNION_PAY,new UnionPay());
    }

    public static Payment get(String payKey){
        if(!strategy.containsKey(payKey)){
            return strategy.get(DEFAULT_PAY);
        }
        return strategy.get(payKey);
    }
}

3. 定义支付结果类

/**
 * 3. 支付结果类
 */
public class MsgResult {
    private int code;
    private Object data;
    private String msg;

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

    @Override
    public String toString() {
        return "MsgResult{" +
                "code=" + code +
                ", data=" + data +
                ", msg='" + msg + '\'' +
                '}';
    }
}

4. 定义订单交易类

/**
 * 4. 订单交易类
 */
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;
    }

    public MsgResult pay(){
        return pay(PayStrategy.DEFAULT_PAY);
    }

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

5. 测试类

/**
 * 测试类
 */
public class Test {
    public static void main(String[] args) {
        Order order = new Order("1","2020031401000323",500);
        System.out.println(order.pay());

        order = new Order("2","2020031401000324",121.5);
        System.out.println(order.pay(PayStrategy.UNION_PAY));

        order = new Order("2","2020031401000324",200);
        System.out.println(order.pay(PayStrategy.WECHAT_PAY));
    }
}

测试结果

-------------------------------------------------------
欢迎使用支付宝
本次交易金额为500.0,开始扣款
MsgResult{code=200, data=支付金额500.0, msg='支付成功'}

欢迎使用银联支付
本次交易金额为121.5,开始扣款
MsgResult{code=500, data=余额不足, msg='支付失败'}

欢迎使用微信支付
本次交易金额为200.0,开始扣款
MsgResult{code=200, data=支付金额200.0, msg='支付成功'}
-------------------------------------------------------

六、策略模式优点

  1. 策略模式符合开闭原则.
  2. 避免使用多重条件转移语句, 如 if...else..等
  3. 使用策略模式可以提高算法的保密性和安全性.

七、策略模式缺点

  1. 客户端必须知道所有的策略, 并且自行决定使用哪一个策略.
  2. 代码中会产生非常多的策略类, 增加维护难度.
最后修改:2022 年 06 月 23 日
如果觉得我的文章对你有用,请点个赞吧~