# 策略模式

该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户

模拟支付,策略实现!我们支付方式有微信支付,支付宝,银行卡.....等等 if payType == 微信支付 then 微信支付流程
if payType == 支付宝支付 then 支付宝支付流程
if payType == 银行卡支付 then 银行卡支付流程

如上代码,虽然写起来简单,但违反了面向对象的 2 个基本原则,单一职责原则和开闭原则。特别是当 if-else 块中的代码量比较大时,后续的扩展和维护会变得非常复杂

# 1.策略的定义

  1. 策略接口的定义,通常包含两个方法:获取策略类型的方法和处理策略业务逻辑的方法
//第三方支付
public interface Payment {
    //获取支付方式
    PayTypeEnum getPayType();
    //支付调用
    PayResult pay(Order order);
}
1
2
3
4
5
6
7
  1. 策略接口的实现 每种支付类都实现了上述接口(基于接口而非实现编程),这样我们可以灵活的替换不同的支付方式。下边示例代码展示了每种支付方式的实现
//支付宝支付
public class AlipayPayment implements Payment {

    @Override
    public PayTypeEnum getPayType() {
        return PayTypeEnum.ALIPAY;
    }

    @Override
    public PayResult pay(Order order) {
        try {
            System.out.println("调用支付宝支付...");
            return PayResult.SUCCESS;
        } catch (Exception e) {
            return PayResult.FAIL;
        }
    }
}

//微信支付
public class WxPayment implements Payment {

    @Override
    public PayTypeEnum getPayType() {
        return PayTypeEnum.WX;
    }

    @Override
    public PayResult pay(Order order) {
        try {
            System.out.println("调用微信支付...");
            return PayResult.SUCCESS;
        } catch (Exception e) {
            return PayResult.FAIL;
        }
    }
}

//银行卡支付
public class BankCardPayment implements Payment {
    @Override
    public PayTypeEnum getPayType() {
        return PayTypeEnum.BANK_CARD;
    }

    @Override
    public PayResult pay(Order order) {
        try {
            System.out.println("调用银行卡支付...");
            return PayResult.SUCCESS;
        } catch (Exception e) {
            return PayResult.FAIL;
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

# 2.策略的组建,即策略上下文

public class PaymentContext {
    private static final Map<PayTypeEnum, Payment> payStrategies = new HashMap<>();

    static {
        payStrategies.put(PayTypeEnum.BANK_CARD, new BankCardPayment());
        payStrategies.put(PayTypeEnum.ALIPAY, new AlipayPayment());
        payStrategies.put(PayTypeEnum.WX, new WxPayment());
    }

    public static Payment getPayment(PayTypeEnum payType) {
        if (payType == null) {
            throw new IllegalArgumentException("pay type is empty.");
        }
        if (!payStrategies.containsKey(payType)) {
            throw new IllegalArgumentException("pay type not supported.");
        }
        return payStrategies.get(payType);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 3.策略的使用

Order order = 订单信息
PayResult payResult = PaymentContext.getPayment(payType).pay(order);
1
2