很多情况下,一个软件系统中可以处理某个请求的对象不知一个,比如采购单的审批,主任,副董事长,董事长,董事会都可以处理采购单,他们可以构成一条处理采购单的链式结构,采购单沿着这条链进行传递,这条链就叫职责链。
职责链可以是一条直线,一个环或者一个树形结构,最常见的职责链是直线型,即沿着一条单向的链来传递请求。链上的每一个对象都是请求处理者,职责链模式可以将请求的处理者组织成一条链,并让请求沿着链传递,由链上的处理者对请求进行处理,客户端无须关系请求的处理细节以及具体的传递,只需要将请求发送到链上即可,实现请求发送者以及请求处理者的解耦。
职责链模式:避免将请求发送者与接收者耦合在一起,让多个对象都有机会接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
职责链模式是一种行为型模式。
Handler
(抽象处理者):定义一个处理请求的接口,一般为抽象类。因为每一个处理者的下家还是一个处理者,因此在抽象处理者中定义了一个抽象处理者的对象作为对下一个处理者的引用,通过该引用,处理者可以连成一条链ConcreteHandler
(具体处理者):抽象处理者的子类,实现具体处理方法,在处理前需要判断是否具有处理权限,如果拥有权限则处理,没有则转发到下一个处理者protected
abstract class Handler
{
protected Handler successor;
public void setSuccessor(Handler successor)
{
this.successor = successor;
}
public abstract void handleRequest(int num);
}
拥有一个设置下一处理者的对象,可以通过setter注入,同时声明抽象处理方法。
class ConcreteHandler1 extends Handler
{
@Override
public void handleRequest(int num)
{
if(num < 10)
{
System.out.println("处理小于10的数字:"+num);
}
else
successor.handleRequest(num);
}
}
class ConcreteHandler2 extends Handler
{
@Override
public void handleRequest(int num)
{
if(num < 20)
{
System.out.println("处理大于等于10且小于20的数字:"+num);
}
else
successor.handleRequest(num);
}
}
class ConcreteHandler3 extends Handler
{
@Override
public void handleRequest(int num)
{
if(num < 30)
{
System.out.println("处理大于等于20且小于30的数字:"+num);
}
else
successor.handleRequest(num);
}
}
继承抽象处理者,首先判断是否拥有权限处理(这里是一个简单的if判断),如果有就处理,没有的话通过protected
对象,也就是转发给下一个处理者处理。
public static void main(String[] args)
{
Handler handler = new ConcreteHandler1();
Handler handler2 = new ConcreteHandler2();
Handler handler3 = new ConcreteHandler3();
handler.setSuccessor(handler2);
handler2.setSuccessor(handler3);
handler.handleRequest(3);
handler.handleRequest(15);
handler.handleRequest(22);
}
客户端针对抽象处理者编程,需要创建每一个具体处理者对象,并且自定义职责链:
handler.setSuccessor(handler2);
handler2.setSuccessor(handler3);
接着调用对应的处理者处理即可。
设计一个采购单审批系统,分级进行,根据金额不同由不同层次的人员审批,主任可以审批5w以下的采购单,副董事长可以审批5w-10w,董事长可以审批10w-50w,50w以上需要由董事会审批,使用职责链模式设计该系统。
设计如下:
Approver
Director
+VicePresident
+President
+Congress
PurchaseRequest
代码如下:
//抽象处理者
abstract class Approver
{
protected Approver successor;
public void setSuccessor(Approver successor) {
this.successor = successor;
}
public abstract void processRequest(PurchaseRequest request);
}
//具体处理者:主任
class Director extends Approver
{
@Override
public void processRequest(PurchaseRequest request)
{
if(request.getAmount() < 50000)
System.out.println("主任审批一笔\n金额为"+request.getAmount()+"\nid为"+request.getId()+"\n的采购单\n");
else
successor.processRequest(request);
}
}
//具体处理者:副董事长
class VicePresident extends Approver
{
@Override
public void processRequest(PurchaseRequest request)
{
if(request.getAmount() < 100000)
System.out.println("副董事长审批一笔\n金额为"+request.getAmount()+"\nid为"+request.getId()+"\n的采购单\n");
else
successor.processRequest(request);
}
}
//具体处理者:董事长
class President extends Approver
{
@Override
public void processRequest(PurchaseRequest request)
{
if(request.getAmount() < 500000)
System.out.println("董事长审批一笔\n金额为"+request.getAmount()+"\nid为"+request.getId()+"\n的采购单\n");
else
successor.processRequest(request);
}
}
//具体处理者:董事会
class Congress extends Approver
{
@Override
public void processRequest(PurchaseRequest request)
{
System.out.println("董事会审批一笔\n金额为"+request.getAmount()+"\nid为"+request.getId()+"\n的采购单\n");
}
}
//请求类:采购单
class PurchaseRequest
{
private double amount;
private String id;
private static final String STR = "xcnvj232cvm";
private static final Random random = new Random();
public PurchaseRequest(double amount)
{
this.amount = amount;
//简易的随机字符串
this.id = STR.substring(0,random.nextInt(STR.length()-1)+1).repeat(random.nextInt(3)+2);
}
public double getAmount() {
return this.amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
}
测试:
public static void main(String[] args)
{
Approver director = new Director();
Approver vicePresident = new VicePresident();
Approver president = new President();
Approver congress = new Congress();
director.setSuccessor(vicePresident);
vicePresident.setSuccessor(president);
president.setSuccessor(congress);
director.processRequest(new PurchaseRequest(12345));
director.processRequest(new PurchaseRequest(54321));
director.processRequest(new PurchaseRequest(123456));
director.processRequest(new PurchaseRequest(654321));
}
职责链模式可以分为纯的职责链模式与不纯的职责链模式。
一个纯的职责链模式要求一个具体处理者对象只能在两个行为中选择一个,要么承担全部责任,要么将责任推给下家,不允许出现某一个具体处理者对象在承担了一部分或全部责任后又将责任向下传递的情况。
而且在纯的职责链模式中,要求一个请求必须被某一个处理者对象接收,不能出现某个请求未被任何一个处理者对象处理的情况,比如前面的采购单例子。
在一个不纯的职责链模式中,允许某个请求被一个具体处理者部分处理后再向下传递,或者一个具体处理者处理完某请求后其猴戏处理者可以继续处理该请求,而且一个请求可以最终不被任何处理者对象所接收。
在Java AWT 1.0中的事件处理模型应用就是不纯的职责链模式,基本原理如下:由于窗口组件一般位于容器组件中,当事件发生在窗口组件上时,先通过组件对象的handleEvent()
方法传递给相应的事件处理方法,该事件处理方法将处理该事件,然后决定是否将该事件向上一级容器组件传播,上级容器组件在接到事件之后可以继续处理此事件并决定是否继续向上级容器组件传播,直到顶层容器组件为止。如果一直都没有处理方法则不处理该事件。
这种事件处理机制又叫事件浮升机制,JDK1.1后使用观察者模式来代理职责链模式处理事件。
如果觉得文章好看,欢迎点赞。
同时欢迎关注微信公众号:氷泠之路。