一、模式动机
职责链可以是一条直线、一个环或者一个树形结构,最常见的职责链是直线型,即沿着一条单向的链来传递请求。
链上的每一个对象都是请求处理者,职责链模式可以将请求的处理者组织成一条链,并使请求沿着链传递,由链上的处理者对请求进行相应的处理。
客户端无须关心请求的处理细节以及请求的传递,只需将请求发送到链上即可,将请求的发送者和请求的处理者解耦。这就是职责链模式的模式动机。
二、模式定义
职责链模式(Chain of Responsibility Pattern):避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。职责链模式又称为责任链模式,它是一种对象行为型模式。
三、模式结构
四、参与者
- Handler: 抽象处理者
- ConcreteHandler: 具体处理者
- Client: 客户类
五、示例代码
package design.pattern;
// 申请
class Request {
private String requestType;
private String requestContent;
private int number;
public String getRequestType() {
return requestType;
}
public void setRequestType(String requestType) {
this.requestType = requestType;
}
public String getRequestContent() {
return requestContent;
}
public void setRequestContent(String requestContent) {
this.requestContent = requestContent;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
// 管理者
abstract class Manager {
protected String name;
protected Manager superior;
public Manager(String name) {
this.name = name;
}
public void setSuperior(Manager manager) {
this.superior = manager;
}
public abstract void requestApplications(Request request);
}
// 经理
class CommonManager extends Manager {
public CommonManager(String name) {
super(name);
}
public void requestApplications(Request request) {
if (request.getRequestType().equals("请假") && request.getNumber() <= 2) {
System.out.println(name + ":" + request.getRequestContent() + " 数量" + request.getNumber() + " 被批准");
} else if (superior != null) {
superior.requestApplications(request);
}
}
}
// 总监
class Majordomo extends Manager {
public Majordomo(String name) {
super(name);
}
public void requestApplications(Request request) {
if (request.getRequestType().equals("请假") && request.getNumber() <= 5) {
System.out.println(name + ":" + request.getRequestContent() + " 数量" + request.getNumber() + " 被批准");
} else if (superior != null) {
superior.requestApplications(request);
}
}
}
// 总经理
class GeneralManager extends Manager {
public GeneralManager(String name) {
super(name);
}
public void requestApplications(Request request) {
if (request.getRequestType().equals("请假")) {
System.out.println(name + ":" + request.getRequestContent() + " 数量" + request.getNumber() + " 被批准");
} else if (request.getRequestType().equals("加薪") && request.getNumber() <= 500) {
System.out.println(name + ":" + request.getRequestContent() + " 数量" + request.getNumber() + " 被批准");
} else if (request.getRequestType().equals("加薪") && request.getNumber() > 500) {
System.out.println(name + ":" + request.getRequestContent() + " 数量" + request.getNumber() + " 再说吧");
}
}
}
public class ChainOfResponsibility {
public static void main(String[] args) {
CommonManager jinli = new CommonManager("金利");
Majordomo zongjian = new Majordomo("宗剑");
GeneralManager zhongjingli = new GeneralManager("钟精励");
jinli.setSuperior(zongjian);
zongjian.setSuperior(zhongjingli);
Request request = new Request();
request.setRequestType("请假");
request.setRequestContent("张三请假");
request.setNumber(1);
jinli.requestApplications(request);
Request request3 = new Request();
request3.setRequestType("加薪");
request3.setRequestContent("张三请求加薪");
request3.setNumber(500);
jinli.requestApplications(request3);
}
}
模式结构
优点
- 降低耦合度
- 可简化对象的相互连接
- 增强给对象指派职责的灵活性
- 增加新的请求处理类很方便
缺点
- 不能保证请求一定被接收。
- 系统性能将受到一定影响,而且在进行代码调试时不太方便;可能会造成循环调用。
- 超长的职责链,性能损失非常大,避免出现超长职责链。
模式使用
- 有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。
- 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
- 可动态指定一组对象处理请求
模式比较
- 职责链模式:当客户提交一个请求时,请求是沿链传递直至有一个ConcreteHander对象负责处理它。链中的对象自己并不知道链的结构,在运行时确定。结果是职责链可简化对象的相互连接,它们仅需保持一个指向其后继者的引用或指针,而不需要保持它所有的候选接受者。这也就大大降低了耦合度了。也就是说,我们可以随时地增加或修改处理一个请求的结构。增强了给对象指派职责的灵活性。
- 状态模式:状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。定义新的子类可以很容易地增加新的状态和转换。这样做的目的是为了消除庞大的条件分支语句。状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖。
- 职责链模式与状态模式的最大的不同是设置自己的下一级的问题上,状态模式是在类的设计阶段就定好的,不能在客户端改变,而职责链的下一级是在客户端自己来确定的。
- 职责链模式注重职责的传递,由客户端配置;状态模式注重对象状态的转换,转换过程对客户端是透明的。