java设计模式-策略模式(一)

基于springboot环境下开发,springboot环境搭建想必大家早已熟悉。

官方解释:在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。在策略模式中,我们创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法

聪明的你看完是否一脸懵逼吧?说实话反正我是懵了,感觉和没说一样。我们就用贴近实际的例子入手。楼主是做第三方支付的,那就以支付来说吧。
某天产品经理说,我们对接了支付宝和微信。废话不说了开干。
先定义接口:

/**
 * Created by lifeng on 2019/8/15.
 * 支付方式接口
 */
public interface PayType {
    public void pay(PayOrderVo vo);//PayOrderVo 为参数对象
}

也可以使用抽象类(推荐使用接口,如果已经忘记抽象类与接口的区别的,需要翻笔记啦)

/**
 * Created by lifeng on 2019/8/15.
 * 抽象类支付方法
 */
public abstract class AbstractPayType {
    public abstract void pay(PayOrderVo payOrderVo);
}

微信支付实现类:

/**
 * Created by lifeng on 2019/8/15.
 * 微信支付
 */
@Service("wechat")
public class WeChatPayService implements PayType{
    @Override
    public void pay(PayOrderVo vo) {
        //此处通过payOrderVo 组装调起微信支付的参数
        System.out.println("微信支付");
    }
}

支付宝实现类:

/**
 * Created by lifeng on 2019/8/15.
 * 支付宝支付
 */
@Service("ali")
public class AliPayService implements PayType{
    @Override
    public void pay(PayOrderVo vo) {
        //此处通过payOrderVo 组装调起支付宝支付的参数
        System.out.println("支付宝支付");
    }
}

选择支付方式:

@Service
public class PayTypeSelect {
    @Resource
    private WeChatPayService weChatPayService;
    @Resource
    private AliPayService aliPayService;
    /**
     * 支付方式选择
     * */
    public PayType select(String payTypeFlag){
        if("ali".equals(payTypeFlag)){
            return weChatPayService;
        }else if("wechat".equals(payTypeFlag)){
            return aliPayService;
        }else{
            throw new RuntimeException("找不到"+payTypeFlag+"此支付方式");
        }
    }
}

在controller我们调用支付:

@RestController
public class StrategyController {
    @Resource
    private PayTypeSelect payTypeSelect;

    @RequestMapping("/orderPay")
    public String orderPay1(String payStyle){
        PayType payType = payTypeSelect.select(payStyle);
        payType.pay(new PayOrderVo());
        return "ok";
    }
}

浏览器直接分别访问http://ip:port/orderPay?payStyle=ali
http://ip:port/orderPay?payStyle=wechat
java设计模式-策略模式(一)_第1张图片
至此,开发完成。过段时间产品又来需要说,再对接中国银联,你可能会做出如下修改:
中国银联实现类:

/**
 * Created by lifeng on 2019/8/15.
 * 银联支付
 */
@Service("union")
public class UnionPayService implements PayType{
    @Override
    public void pay(PayOrderVo vo) {
        //此处通过payOrderVo 组装调起支付的参数
        System.out.println("中国银联支付");
    }
}

然后对支付方法选择类做如下修改:

@Service
public class PayTypeSelect {
    @Resource
    private WeChatPayService weChatPayService;
    @Resource
    private AliPayService aliPayService;
    @Resource
    private UnionPayService unionPayService;
    /**
     * 支付方式选择
     * */
    public PayType select(String payTypeFlag){
        if("ali".equals(payTypeFlag)){
            return weChatPayService;
        }else if("wechat".equals(payTypeFlag)){
            return aliPayService;
        }else if("union".equals(payTypeFlag)){
            return unionPayService;
        }else{
            throw new RuntimeException("找不到"+payTypeFlag+"此支付方式");
        }
    }
}

我想有点经验的开发人员都已经看出问题所在了:
1.在有多种支付方式的情况下,使用 if…else 所带来的复杂和难以维护。
2.扩展性很差。

下面我们只要对支付方式选择稍加调整:

	/**
     * 支付方式选择
     * */
    public PayType select(String payTypeFlag){
        PayType payType = (PayType) MySpringUtil.applicationContext.getBean(payTypeFlag);
        return payType;
    }

MySpringUtil是获取spring中的bean:

@Component
public class MySpringUtil implements ApplicationContextAware {
    public static ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

这样一来,以后不管来多少种支付方式,原有代码无需改动,只需添加支付方式。
这就是前辈们总结出来的策略模式。我们要结合自己项目的场景,灵活应用。
优点: 1、实现类可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。
缺点: 1、策略类会增多。 2、所有策略类都需要对外暴露。
注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。
代码在码云可参考 https://gitee.com/lifengit/javapatterns

你可能感兴趣的:(java设计模式-策略模式(一))