本文转载自微信公众号《程序新视界》,作者为二师兄。转载本文请联系程序新视界公众号。前言策略模型以前在三方支付系统中经常用到。比如用户会选择不同的支付方式,不同的支付方式有不同的实现方式或者银行接口调用。现在的物联网系统都是基于MQTT协议(TCP层面的协议)传输数据,根据不同的请求(不同的Topics)处理不同的业务逻辑,也使用策略模型。顿时觉得策略模式很好用,结合Spring的实例化和注入功能,更加方便。今天我们就来说说基于Spring(Boot)的策略模式的使用。不使用策略模式时的处理以物联网为例,大家可能不熟悉,下面以支付场景为例。比如在支付过程中,我们可能会选择微信支付、支付宝支付或者银卡支付。同时,银行卡也分不同的银行,这里统称为银行卡。最简单直接的代码实现如下:){System.out.println("微信支付");}elseif("bank".equals(payType)){System.out.println("银行卡支付");}}这种比较设计模式通常不满足两大原则:单一职责原则和开放封闭原则。我们会发现当前的类(或方法)并没有处理多个业务的功能。任何支付方式一经修改,其他支付方式可能会受到影响。同时,也不可能对扩展开放,对修改关闭。添加其他支付方式时,ifelse判断也要修改,会影响其他业务逻辑。策略模式通常就是解决这种ifelse处理逻辑,从而提高代码的可维护性、可扩展性和可读性。策略模式概述??在改造上面的代码之前,我们先来了解一下策略模式的基本组成。策略模式(Strategy),定义了一组算法,封装了每一个算法,并使它们可以互换。策略模式通常由以下部分组成:Strategy策略类,用于定义所有支持的算法的公共接口;ConcreteStrategy具体的策略类,封装了具体的算法或者行为,继承自Strategy。Context上下文配置了一个ConcreteStrategy来维护对Strategy对象的引用;StrategyFactory策略工厂类用于创建策略类的具体实现;通常这部分可以省略,视具体情况而定。比如在后面的例子中,策略类的实例化就是通过Spring的依赖注入机制来实现的。如下图所示,用类图表示(省略了策略工厂类):image基于Spring的策略模式实现,在实践中通常是根据Spring的特性来实现的。这里,我们就以此为例进行说明。Strategy类定义上面已经说过,strategy类是用来定义函数的接口的。对于支付场景,可以命名为PaymentService或者PaymentStrategy。publicinterfacePaymentService{/***payment*/PayResultpay(Orderorder);}也提供了该策略类的不同实现类:AlipayService、WeChatPayService、BankPayService。@Service("alipay")publicclassAlipayServiceimplementsPaymentService{@OverridepublicPayResultpay(Orderorder){System.out.println("Alipay");returnnull;}}@Service("wechatPay")publicclassWeChatPayServiceimplementsPaymentService{@OverridepublicPayResultpay(Orderorder){System.out.println("WeChatPay");returnnull;}}@Service("bank")publicclassBankPayServiceimplementsPaymentService{@OverridepublicPayResultpay(Orderorder){System.out.println("BankPay");returnnull;}}可以通过一个PaymentFactory实例化来构建存储,或者直接使用@Autowired的形式注入到Context的List或者Map中。PaymentFactory的实现如下:);payStrategies.put("bank",newBankPayService());}publicstaticPaymentServicegetPayment(StringpayType){if(payType==null){thrownewIllegalArgumentException("paytypeisempty.");}if(!payStrategies.containsKey(payType)){thrownewIllegalArgumentException("paytypenotsupported.");}returnpayStrategies.get(payType);}}通过static静态代码块初始化对应的策略实现类,然后根据支付类型提供getPayment方法获取对应的服务。当然,通过static初始化的代码块是单例无状态的。如果需要一个有状态的类,则getPayment方法需要每次都是新的。publicstaticPaymentServicegetPayment1(StringpayType){if(payType==null){thrownewIllegalArgumentException("paytypeisempty.");}if("alipay".equals(payType)){returnnewAlipayService();}elseif("wechatPay".equals(payType)){returnnewWeChatPayService();}elseif("bank".equals(payType)){returnnewBankPayService();}thrownewIllegalArgumentException("paytypenotsupported.");}Context上下文上下文角色,也叫Context封装角色,作为前面的链接以及以下,屏蔽高层模块直接访问策略和算法,并封装可能的变化。上面以工厂形式创建的策略类的实现类也可以通过@Autowired直接注入到Context上下文中。@ComponentpublicclassPaymentStrategy{@AutowiredprivatefinalMap
