文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

基于Spring(Boot)下策略模式的使用方法教程

2024-04-02 19:55

关注

这篇文章主要讲解了“基于Spring(Boot)下策略模式的使用方法教程”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“基于Spring(Boot)下策略模式的使用方法教程”吧!

未使用策略模式时的处理

以物联网为例大家可能不够熟悉,下面就以支付场景为例。比如在支付的过程中我们可能会选择微信支付、支付宝支付或银卡支付。同时,银行卡又分不同银行,这里统一为银行卡。

最简单直接的代码实现形式如下:

public void pay(String payType){     if("alipay".equals(payType)){         System.out.println("支付宝");     }else if("wechatPay".equals(payType)){         System.out.println("微信支付");     } else if("bank".equals(payType)){         System.out.println("银行卡支付");     } }

这样对照设计模式,通常不符合两个原则:单一职责原则和开闭原则。

我们会发现当前类(或方法)不处理了多个业务的功能,一旦任何一个支付方式的修改都可能会影响到其他的支付方式。同时,无法做到对扩展开放,对修改关闭。新增其他支付方式时同样要修改ifelse判断,影响到其他的业务逻辑。

而策略模式通常就是解决这种有很多ifelse处理逻辑,从而提高代码的可维护性、可扩展性和可读性。

策略模式的轮廓

在对上述代码进行改造之前,先来了解一下策略模式的基本组成。

策略模式(Strategy),定义了一组算法,将每个算法都封装起来,并且使它们之间可以互换。

策略模式通常由以下几部分组成:

用类图来表示(省略策略工厂类)如下图:

基于Spring(Boot)下策略模式的使用方法教程

image

基于Spring的策略模式实现

目前在实践中通常都是基于Spring的特性来实现策略模式,这里就以此为例来进行讲解。

策略类定义

上面已经提到,策略类用于定义功能的接口,对于支付场景则可命名为PaymentService或PaymentStrategy。

public interface PaymentService {           PayResult pay(Order order); }

同时提供该策略类的不同实现类:AlipayService、WeChatPayService、BankPayService。

@Service("alipay") public class AlipayService implements PaymentService {     @Override     public PayResult pay(Order order) {         System.out.println("Alipay");         return null;     } }
@Service("wechatPay") public class WeChatPayService implements PaymentService {     @Override     public PayResult pay(Order order) {         System.out.println("WeChatPay");         return null;     } }
@Service("bank") public class BankPayService implements PaymentService {     @Override     public PayResult pay(Order order) {         System.out.println("BankPay");         return null;     } }

具体实现的实例化,可以通过一个PaymentFactory来进行构建存储,也可以直接利用@Autowired形式注入到Context的List或Map当中。

PaymentFactory的实现如下:

public class PaymentFactory {      private static final Map<String, PaymentService> payStrategies = new HashMap<>();      static {         payStrategies.put("alipay", new AlipayService());         payStrategies.put("wechatPay", new WeChatPayService());         payStrategies.put("bank", new BankPayService());     }      public static PaymentService getPayment(String 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);     } }

通过static静态代码块来初始化对应的策略实现类,然后提供一个getPayment方法,根据支付类型来获取对应的服务。当然,通过static初始化的代码块是单例的无状态的,如果需要有状态的类则getPayment方法,每次都需要new一个新的对象。

public static PaymentService getPayment1(String payType) {     if (payType == null) {         throw new IllegalArgumentException("pay type is empty.");     }     if ("alipay".equals(payType)) {         return new AlipayService();     } else if ("wechatPay".equals(payType)) {         return new WeChatPayService();     } else if ("bank".equals(payType)) {         return new BankPayService();     }     throw new IllegalArgumentException("pay type not supported."); }

Context上下文

Context上下文角色,也叫Context封装角色,起承上启下的作用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。

上面通过工厂的形式创建策略类的实现类,当然也可以直接通过@Autowired注入到Context上下文中。

@Component public class PaymentStrategy {      @Autowired     private final Map<String, PaymentService> payStrategies = new HashMap<>();      public PaymentService getPayment(String 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);     } }

上面通过@Autowired注解,将通过@Service实例化的PaymentService实现类,注入到map当中,其中key为实例化类的名称,value为具体的实例化类。

上面的getPayment代码与PaymentFactory中一致。当然,还可以在PaymentStrategy中封装一个pay方法,这样,客户端直接注入PaymentStrategy类调用pay方法即可。

public PayResult pay(String payType,Order order){     PaymentService paymentService = this.getPayment(payType);     return paymentService.pay(order); }

改进方案

通过上面的代码基本上已经实现了策略模式,此时当新增加一个支付通道时,已经不用修改PaymentStrategy相关的代码,只用新增一个实现PaymentService接口的类即可。

但在接口定义这里,还是有优化空间的。比如,这里判断是通过Bean的名称来判断的,但某些情况下判断可能比较复杂或可能会同时执行多个Service。此时,就可以对PaymentService接口进行改进,新增一个检验是否支持该功能的判断方法。

public interface PaymentService {      boolean isSupport(Order order);           PayResult pay(Order order); }

由实现类来具体实现isSupport方法,判断自己支持哪些功能。

同时,上下文类也可以进一步利用Java8提供的Steam特性进行处理:

@Component public class PaymentStrategy {           @Autowired     private List<PaymentService> paymentServices;      public void pay(Order order) {         PaymentService paymentService = paymentServices.stream()                 .filter((service) -> service.isSupport(order))                 .findFirst()                 .orElse(null);          if (paymentService != null) {             paymentService.pay(order);         } else {             throw new IllegalArgumentException("pay type not supported.");         }     } }

通过进一步改造,程序变得更加灵活了。

感谢各位的阅读,以上就是“基于Spring(Boot)下策略模式的使用方法教程”的内容了,经过本文的学习后,相信大家对基于Spring(Boot)下策略模式的使用方法教程这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-前端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯