设计模式剖析系列之责任链模式

By heiry on 2019-08-19 [ in 技术 ]

责任链模式

责任链模式是将请求发送者与处理者之间的耦合关系降低的一种行为模式。如,在公司中,研发部部长申请一笔部门活动经费,按照公司规定,经费在5万元内研发总监签字即可,经费在5万元至10万元的需要总经理批准,经费在10万元至20万元之间的需要副总裁批准。

按照一般思维,研发部部长必须很熟悉公司规章制度,自行根据金额大小去找不同领导签字,这就无形中增加了额外工作负荷。现在公司开发了一套系统,申请人只需要将金额等基本申请信息填写好,录入系统,系统根据公司规则自动判断该发送到哪个领导审批,相应领导接收到申请后审批,并将审批结果反馈回来。这样申请人无需去额外学习复杂的公司制度,也不需要关心是谁处理了这个申请,申请人和审批领导实现了解耦,提高了效率。这套系统就充当了责任链。

责任链模式的核心角色:

1. 请求类(Request): 包含具体请求参数。

2. 抽象处理者(Handler): 处理请求的共性特征。

3. 具体处理者(Concrete Handler): 实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。

4. 客户端类:创建链实例及指定处理者关系(谁是当前处理者的下一个处理者)。

我们以部门活动经费审批为例,通过责任链模式实现审批功能:

UML类图:

具体代码实现:

package net.mosang.responsibility;
/**
 * 请求类
 * A. 标明经费请求的具体信息
 * @author Heiry
 *
 */
public class RequestAppropriation {
  private int num; //申请的经费金额
  private String reason; //申请的理由
  private String staffName; //申请人姓名
  public RequestAppropriation(int num, String reason, String staffName) {
    super();
    this.num = num;
    this.reason = reason;
    this.staffName = staffName;
  }
  public int getNum() {
    return num;
  }
  public void setNum(int num) {
    this.num = num;
  }
  public String getReason() {
    return reason;
  }
  public void setReason(String reason) {
    this.reason = reason;
  }
  public String getStaffName() {
    return staffName;
  }
  public void setStaffName(String staffName) {
    this.staffName = staffName;
  }
}
package net.mosang.responsibility;
/**
 * 抽象处理类Handler:审批领导Leader
 * @author Heiry
 *
 */
public abstract class Leader {
  protected String leaderName; // 领导姓名
  protected Leader nextLeader; // 当前领导的下一级别领导
  public abstract void handleRequest(RequestAppropriation r); // 具体审批操作
  
  public Leader(String leaderName, Leader nextLeader) {
    super();
    this.leaderName = leaderName;
    this.nextLeader = nextLeader;
  }
  public Leader(String leaderName) {
    super();
    this.leaderName = leaderName;
  }
  public String getLeaderName() {
    return leaderName;
  }
  public void setLeaderName(String leaderName) {
    this.leaderName = leaderName;
  }
  public Leader getNextLeader() {
    return nextLeader;
  }
  public void setNextLeader(Leader nextLeader) {
    this.nextLeader = nextLeader;
  }
}
package net.mosang.responsibility;
/**
 * 具体处理类:研发总监(R&D Director)
 * 审批权限:五万元内
 * @author Heiry
 *
 */
public class RD extends Leader {
  @Override
  public void handleRequest(RequestAppropriation r) {
    if(r.getNum()<=50000) {
      System.out.println(r.getStaffName()+"申请"+r.getNum()+"元部门活动经费,审批结果如下:");
      System.out.println(this.leaderName+"-->审批通过!"); //在权限范围:5万元内,直接审批通过!
    }
    else {
      this.nextLeader.handleRequest(r);//超过权限,交由下一级别领导处理
    }
  }
  public RD(String leaderName) {
    super(leaderName);
    }
}
package net.mosang.responsibility;
/**
 * 具体处理类:总经理(General Manager)
 * 审批权限:10万元内
 * @author Heiry
 *
 */
public class GM extends Leader {
  @Override
  public void handleRequest(RequestAppropriation r) {
    if(r.getNum()<=100000) {
      System.out.println(r.getStaffName()+"申请"+r.getNum()+"元部门活动经费,审批结果如下:");
      System.out.println(this.leaderName+"-->审批通过!"); //在权限范围:10万元内,直接审批通过!
    }
    else {
      this.nextLeader.handleRequest(r);//超过权限,交由下一级别领导处理
    }
  }
  public GM(String leaderName) {
    super(leaderName);
    }
}
package net.mosang.responsibility;
/**
 * 具体处理类:副总裁(Vice President)
 * 审批权限:20万元内
 * @author Heiry
 *
 */
public class VP extends Leader {
  @Override
  public void handleRequest(RequestAppropriation r) {
    if(r.getNum()<=200000) {
      System.out.println(r.getStaffName()+"申请"+r.getNum()+"元部门活动经费,审批结果如下:");
      System.out.println(this.leaderName+"-->审批通过!"); //在权限范围:20万元内,直接审批通过!
    }
    else {
      //副总裁没有下一任审批人,责任链末端,返回系统默认处理信息
      System.out.println("活动经费超出20万元,超过公司规定,系统自动驳回!");//超过20万元,公司没有此活动经费预算规定,自动驳回
    }
  }
  public VP(String leaderName) {
    super(leaderName);
    }
}
package net.mosang.responsibility;
/**
 * 客户端类
 * @author Heiry
 *
 */
public class Client {
  public static void main(String[] args) {
    RD rd = new RD("研发总监A"); // 创建研发总监实例
    GM gm = new GM("总经理B"); // 创建总经理实例
    VP vp = new VP("副总裁C"); // 创建副总裁实例
    rd.setNextLeader(gm); // 设置研发总监A下一级别审批领导为总经理B
    gm.setNextLeader(vp); // 设置研发总经理B下一级别审批领导为副总裁C
    RequestAppropriation r = new RequestAppropriation(30000, "部门小聚", "研发部长H"); //申请3万元活动经费
    RequestAppropriation r2 = new RequestAppropriation(80000, "部门小聚", "研发部长H"); //申请8万元活动经费
    RequestAppropriation r3 = new RequestAppropriation(150000, "部门小聚", "研发部长H"); //申请15万元活动经费
    RequestAppropriation r4 = new RequestAppropriation(500000, "部门小聚", "研发部长H"); //申请50万元活动经费
    rd.handleRequest(r);
    System.out.println("############################");
    rd.handleRequest(r2);
    System.out.println("############################");
    rd.handleRequest(r3);
    System.out.println("############################");
    rd.handleRequest(r4);
  }
}

 

输出结果:

研发部长H申请30000元部门活动经费,审批结果如下:
研发总监A-->审批通过!
############################
研发部长H申请80000元部门活动经费,审批结果如下:
总经理B-->审批通过!
############################
研发部长H申请150000元部门活动经费,审批结果如下:
副总裁C-->审批通过!
############################
活动经费超出20万元,超过公司规定,系统自动驳回!

在责任链模式下,经费申请人研发部部长无需对公司制度了解得很透彻(申请金额对应的审批领导),只需要将基本申请信息提交到责任链上,甚至不关心是谁审批了这个申请,就能得到申请结果。这样,请求发送者与处理者之间就解耦了。

另外,如果在责任链中,再增加请求处理者,也就是中间再增加审批人,只要新增相应的类和改动客户端类就行了,不需要改动已有责任链类代码,符合开闭原则,利于功能扩展。

 >>



© 2009-2024 MOSANG.NET DESIGNED BY HEIRY