一、职责链(Chain of Responsibility)模式
- 模式定义与特点
- 责任链模式属于对象的行为模式范畴。在这一模式中,众多对象相互连接形成一条链,连接的方式是每个对象都持有对其下一个对象(下家)的引用。当一个请求在这条链上传递时,它会依次经过各个对象,直到链上的某个对象决定对该请求进行处理。对于发出请求的客户端而言,它并不清楚链上究竟哪个对象最终会处理这个请求。这种特性赋予了系统极大的灵活性,使得系统能够在不影响客户端的情况下,动态地对链进行重新组织和责任分配。
- 以击鼓传花游戏为例,它是责任链模式在实际生活中的一个生动应用。在击鼓传花场景中,参与者们依次传递花束,形成了一种类似责任链的结构。责任链在不同场景下可能呈现出直线、环形链或者树状结构的一部分等多种形态,具体形态取决于实际的业务逻辑和需求。
- 责任链模式的结构
- 涉及角色
- 抽象处理者(Handler)角色:该角色定义了处理请求的接口,为整个责任链模式奠定了基础。在某些情况下,如果需要,这个接口还可以定义用于设置和获取下家引用的方法。通常,抽象处理者由抽象类或接口来实现,它为具体处理者提供了统一的行为规范和接口定义。
- 具体处理者(ConcreteHandler)角色:具体处理者在接到请求后,拥有两种处理方式可供选择。它可以根据自身的逻辑判断,决定是否处理该请求。如果当前具体处理者有能力处理请求,它将执行相应的处理逻辑;反之,如果它认为自己无法处理该请求,或者根据业务规则需要将请求传递给更合适的处理者,它就会将请求传递给下家。由于具体处理者持有对下家的引用,所以它能够方便地将请求转发给下一个对象,实现请求在责任链上的传递。
- 涉及角色
- 责任链模式的示意性源代码(Java版)
// Chain of Responsibility pattern -- Structural example
abstract class Handler {
// Fields
protected Handler successor;
// Methods
public void setSuccessor(Handler successor) {
this.successor = successor;
}
abstract public void handleRequest(int request);
}
class ConcreteHandler1 extends Handler {
// Methods
@Override
public void handleRequest(int request) {
if (request >= 0 && request < 10) {
System.out.println(this + " handled request " + request);
} else if (successor!= null) {
successor.handleRequest(request);
}
}
}
class ConcreteHandler2 extends Handler {
// Methods
@Override
public void handleRequest(int request) {
if (request >= 10 && request < 20) {
System.out.println(this + " handled request " + request);
} else if (successor!= null) {
successor.handleRequest(request);
}
}
}
class ConcreteHandler3 extends Handler {
// Methods
@Override
public void handleRequest(int request) {
if (request >= 20 && request < 30) {
System.out.println(this + " handled request " + request);
} else if (successor!= null) {
successor.handleRequest(request);
}
}
}
// Client test
public class Client {
public static void main(String[] args) {
// Setup Chain of Responsibility
Handler h1 = new ConcreteHandler1();
Handler h2 = new ConcreteHandler2();
Handler h3 = new ConcreteHandler3();
h1.setSuccessor(h2);
h2.setSuccessor(h3);
// Generate and process request
int[] requests = { 2, 5, 14, 22, 18, 3, 27, 20 };
for (int request : requests) {
h1.handleRequest(request);
}
}
}
- 纯的与不纯的责任链模式
- 纯的责任链模式:在纯责任链模式中,对于一个具体的处理者对象而言,它在面对请求时,只能严格地在承担责任和将责任推给下家这两种行为中做出选择,绝对不允许出现既承担了一部分责任后又将剩余责任向下传递的情况。而且,在这种模式下,一个请求必定会被链上的某个处理者对象所接收和处理,不存在请求被忽略的情况。然而,在实际应用中,纯责任链模式的例子相对较少,其实现和应用场景相对较为受限。
- 不纯的责任链模式:与纯责任链模式不同,不纯的责任链模式允许一个请求在传递过程中,最终不被任何接收端对象所接收。这种模式在实际开发中更为常见,因为它能够更好地适应复杂多变的业务需求。例如,在某些情况下,根据业务规则,一个请求可能在经过一系列处理者后,发现没有合适的处理者能够处理它,此时系统可以选择采取其他策略,如记录日志、返回错误信息等。
- 责任链模式的实际应用案例(Java版)
// Chain of Responsibility pattern -- Real World example
abstract class Approver {
// Fields
protected String name;
protected Approver successor;
// Constructors
public Approver(String name) {
this.name = name;
}
// Methods
public void setSuccessor(Approver successor) {
this.successor = successor;
}
abstract public void processRequest(PurchaseRequest request);
}
class Director extends Approver {
// Constructors
public Director(String name) {
super(name);
}
// Methods
@Override
public void processRequest(PurchaseRequest request) {
if (request.getAmount() < 10000.0) {
System.out.println(this + " " + name + " approved request# " + request.getNumber());
} else if (successor!= null) {
successor.processRequest(request);
}
}
}
class VicePresident extends Approver {
// Constructors
public VicePresident(String name) {
super(name);
}
// Methods
@Override
public void processRequest(PurchaseRequest request) {
if (request.getAmount() < 25000.0) {
System.out.println(this + " " + name + " approved request# " + request.getNumber());
} else if (successor!= null) {
successor.processRequest(request);
}
}
}
class President extends Approver {
// Constructors
public President(String name) {
super(name);
}
// Methods
@Override
public void processRequest(PurchaseRequest request) {
if (request.getAmount() < 100000.0) {
System.out.println(this + " " + name + " approved request# " + request.getNumber());
} else {
System.out.println("Request# " + request.getNumber() + " requires an executive meeting!");
}
}
}
class PurchaseRequest {
private double amount;
private int number;
public PurchaseRequest(double amount, int number) {
this.amount = amount;
this.number = number;
}
public double getAmount() {
return amount;
}
public int getNumber() {
return number;
}
}
在这个实际应用案例中,通过定义不同层次的审批者(如主管、副总裁、总裁),并利用责任链模式将它们连接起来,实现了根据购买请求金额大小进行审批决策的流程。当一个购买请求被提交后,它会沿着责任链依次传递,直到找到能够处理该请求的审批者。如果金额较小,可能在较低层级的审批者(如主管)处就得到批准;如果金额较大,则会依次传递给更高层级的审批者(如副总裁、总裁)进行决策。这种设计模式使得系统在处理不同金额的购买请求时,能够灵活地选择合适的审批流程,同时也便于系统的扩展和维护。例如,如果未来需要添加新的审批层级或者修改审批规则,只需要在相应的审批者类中进行修改,而不会对整个系统的结构产生重大影响。