设计模式(三) 策略模式

Posted by hang.li on November 20, 2022

借用设计模式(二)中的案例

问题分析

  • 在Demo中部分代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    /**
     * 重置密码方法
     */
    public void resetPassword() {
        String smsType = "huawei";
        sendCodeSMS(smsType, new HashMap<>());
    }

    public Map sendCodeSMS(String smsType, Map<String, String> paramMap) {
        if ("ali".equals(smsType)) {
            // TODO 可实现按照适配器命名规则, 利用反射初始化适配器
//            smsService = new AliSmsAdapter();
        } else if ("tencent".equals(smsType)) {
            // TODO 可实现按照适配器命名规则, 利用反射初始化适配器
//            smsService = new TencentSmsAdapter();
        } else if ("hauwei".equals(smsType)) {
            // TODO 可实现按照适配器命名规则, 利用反射初始化适配器
//            smsService = new HuaweiSmsAdapter();
        }
        return smsService.sendCodeSMS(paramMap);
    }
  • 如果此时系统中短信平台增加七牛云, 不仅要实现其七牛的Adapter, 而且还要在此处添加一个判断平台的判断,还是需要在调用方进行修改,程序还有优化的空间
  • 每一种平台,更像是一种策略,而策略的选用在调用时就能确定.

    UML

    此时Demo类对SmsService的依赖(原组合关系),转换为了Demo.getAdapterBySmsType()方法对SmsService的依赖(依赖关系) img.png

    修改后的Demo.java代码

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
public class Demo {
    /**
     * 注册方法
     */
    public void regist() {
        String smsType = "huawei";
        sendCodeSMS(getAdapterBySmsType(smsType), new HashMap<>());
    }

    /**
     * 重置密码方法
     */
    public void resetPassword() {
        String smsType = "huawei";
        sendCodeSMS(getAdapterBySmsType(smsType), new HashMap<>());
    }

    public Map sendCodeSMS(SmsService smsService, Map<String, String> paramMap) {
        return smsService.sendCodeSMS(paramMap);
    }

    private SmsService getAdapterBySmsType(String smsType) {
    	// 此时如果增加平台,只需要按照相同的规则定义七牛短信平台的Adapter即可使用
        // TODO 根据规则,选用策略逻辑
        return null;
    }
}