责任链模式在业务场景中应用

责任链模式是一种设计模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任

-百度百科

写了这么多年代码,我一直秉承着 以无形胜有形 的风格去累代码,我也常常的去看 《设计模式》尝试着从里面找到一种牛B的模式来解决,解耦业务代码!前人的经验总是值得我们去学习的,老话说的好:“吃的盐比你吃的饭还多”。这次刚好写一个支付接口,经过业务分析,我想到了 23种设计模式中的 责任链模式。 刚好可以拿来借鉴!

业务需求

现有一个支付接口需求,能接受 多种的支付方式 。比如:一个订单要支付 100块钱,客户端提交过来一个支付列表,比如:现金:50,扫支付宝码:20,系统红包账户支付:30元!

正常思维代码实现

正常我们来实现这种需求,就直接

public void pay(List<payListDTO> payList) {
    
    for (payList as pay) {
    
        if (pay == “微信“) {
        
        }
    
         if (pay == “支付宝“) {
        
         }
    
         if (pay == “扫码支付“) {
        
        }
    }
}

上面的代码很简单,也很明了!但是作为一个年长的开发者,是不能容忍的!至于为什么不能容忍,我这里也不表明客套话了,网上多的很!

业界内一神话:“高内聚,低耦合”。以这个视角去看上面的代码,一个好的内聚模块(这里可以看每一个 if里做的事情) 应该是单独的一个方法或者一个类,以方便代码的复用性,解除方法随着需求的迭代而变的很难维护。

那么我们尝试着利用前人累积下的智慧来改造这段代码!

改造

  1. 首先定义一个标准,定义抽象方法
public abstract class Payhander {
    
    //定义支付行为
    public abstract boolean pay(PayContext cnt)
}
  1. 定义现金支付类 实现 标准
@Component("cashPayHander")
class CashPayHander extends Payhander {

    public boolean pay(PayContext cnt) {
    
           //现金支付逻辑
    }
}
  1. 定义余额支付类 实现 标准
@Component("balancePayHander")
class BalancePayHander extends Payhander {

    public boolean pay(PayContext cnt) {
    
         //余额支付逻辑
    }
}

定义接口,和实现类简单! 那么接下来是如何把这些类给利用起来?

通过理解责任链里描述 我们还要在每个实现类里定义一个指向下一个实现类的引用!

  1. 改造下抽象接口
public abstract class Payhander {
    
    //定义一个指向下一个处理器的引用
    protected Payhander nextHander;
    
     
    // 这里我新加入一个待字类去实现的下一个引用注入器
    public abstract void setNextHander(PayHander next)
     
        
    //定义 getter,setter由子类实现
    protected PayHander getNexthander() {
        return nextHeader;
    } 
        
        
        
        
        
    
    //定义支付行为
    public abstract boolean pay(PayContext cnt)
}
  1. 改造下现金支付实现类
@Component("cashPayHander")
class CashPayHander extends Payhander {
    
    
    // 这里我是利用Spring 的注入方式来实现自动注入 此时我们这现金支付注入下一个引用 为余额支付
    @Resource
    @Override
    public void setNextHander(PayHander balancePayHander) {
        this.nextHander = balancePayHander;
    }
    
    
   
    
    public boolean pay(PayContext cnt) {
    
           //现金支付逻辑
        
         if (super.getNexthander() != null) {
             //调用下一个处理器
             super.getNexthander().pay(cnt);
         }
    }
}

其他类的改造的类这里就不一一示例出!

经过这样一改造,那么责任链的雏形就在我们脑海里出现了这样的一副图,每个支付业务逻辑单独在每个实现类里做业务逻辑,单个类的利用性得到提高。再加入其他支付方式的时候,只要写入实现,加入链表中即可。

一切看起来VeryGood,但也有不好的地方!

缺点

  1. 如果维护人在每个实现类之前引用没有处理好,容易开成环链,死循环。
  2. 每实现类都会被访问一次,这个是链表的特性。
posted @ 2022-04-17 21:29  乌托拉赛文  阅读(655)  评论(2编辑  收藏  举报