作为一个编程菜鸟,过去在学习设计模式的时候,老师给推荐了一本《大话设计模式》。阅读以后受益匪浅,可惜当初没有坚持看完。
最近有时间了,又重新捡起来学习了一遍,整理了一下笔记,由于本人能力有限,欢迎大家批评指正。
1.职责连模式 Chain of Responsibility
- 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
- 发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
2.uml类图
3.组成
(1)抽象处理者角色 Handler
定义出一个处理请求的借口。如果需要,接口可以定义出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。上图中Handler类的聚合关系给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作。
(2)具体处理者角色 ConcreteHandler
具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。
3.优缺点
- 当客户提交一个请求时,请求是沿链传递直至有一个ConcreteHandler对象负责处理它。
- 接收者和发送者都没有对方的明确信息,且链中的对象自己也并不知道链的结构。结果是职责链可简化对象的相互连接,它们仅需保持一个指向其后继者的引用,而不需要保持它所有的候选接受者的引用,降低了耦合。
- 由于是在客户端来定义链结构,可以随时地增加或修改处理一个请求的结构。增强了给对象指派职责的灵活性。
- 需要当心的是,一个请求极有可能到了链末端都得不到处理,或者因为没有正确配置而得不到处理。需要事先考虑全面。
4.实例
(1)需求
员工提出工作相关的请求需要上级处理审批。
(2)uml类图
(3)代码
a.申请类
package com.longinus.corp;
public class Request {
private String requestType;
private String requestConten;
private int number;
public String getRequestType() {
return requestType;
}
public void setRequestType(String requestType) {
this.requestType = requestType;
}
public String getRequestConten() {
return requestConten;
}
public void setRequestConten(String requestConten) {
this.requestConten = requestConten;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
b.管理者抽象类
package com.longinus.corp;
public abstract class Manager {
protected String name;
//管理者的上级
protected Manager superior;
public Manager(String name) {
this.name = name;
}
//设置管理者的上级
public void setSuperior(Manager superior) {
this.superior = superior;
}
public abstract void requestApplication(Request request);
}
c.具体管理者类
package com.longinus.corp;
/**
* @Title: CommonManager.java
* @Description: 经理类,处理请求
* @author Longinus
* @date 2017年6月26日 下午8:51:28
* @version V1.0
*/
public class CommonManager extends Manager {
public CommonManager(String name) {
super(name);
}
@Override
public void requestApplication(Request request) {
//经理权限为允许下属清两天内的假期
if(request.getRequestType().equals("请假") && request.getNumber() <= 2){
System.out.println(name + ":" + request.getRequestConten()
+ request.getNumber() + "天被批准");
//其余申请转交上级处理
} else {
if(superior != null){
superior.requestApplication(request);
}
}
}
}
package com.longinus.corp;
/**
* @Title: Majordomo.java
* @Description: 总监类,处理请求
* @author Longinus
* @date 2017年6月26日 下午8:56:56
* @version V1.0
*/
public class Majordomo extends Manager {
public Majordomo(String name) {
super(name);
}
@Override
public void requestApplication(Request request) {
//总监权限为允许下属清一周内的假期
if(request.getRequestType().equals("请假") && request.getNumber() <= 5){
System.out.println(name + ":" + request.getRequestConten()
+ request.getNumber() + "天被批准");
//其余申请转交上级处理
} else {
if(superior != null){
superior.requestApplication(request);
}
}
}
}
package com.longinus.corp;
/**
* @Title: GeneralManager.java
* @Description: 总经理类,处理请求
* @author Longinus
* @date 2017年6月26日 下午9:01:42
* @version V1.0
*/
public class GeneralManager extends Manager {
public GeneralManager(String name) {
super(name);
}
@Override
public void requestApplication(Request request) {
//总经理权限为允许下属清两天内的假期
if(request.getRequestType().equals("请假")){
System.out.println(name + ":" + request.getRequestConten()
+ request.getNumber() + "天被批准");
//加薪在五百以内没有问题
} else if(request.getRequestType().endsWith("加薪") && request.getNumber() <= 500) {
System.out.println(name + ":" + request.getRequestConten()
+ request.getNumber() + "被批准");
//加薪大于五百就需要考虑一下了
} else if(request.getRequestType().endsWith("加薪") && request.getNumber() > 500) {
System.out.println(name + ":" + request.getRequestConten()
+ request.getNumber() + "再说吧");
}
}
}
d.测试类
package com.longinus.corp;
public class Test {
public static void main(String[] args) {
CommonManager cm = new CommonManager("经理");
Majordomo m = new Majordomo("总监");
GeneralManager gm = new GeneralManager("总经理");
cm.setSuperior(m);
m.setSuperior(gm);
Request request1 = new Request();
request1.setRequestType("请假");
request1.setRequestConten("李雷请假");
request1.setNumber(1);
cm.requestApplication(request1);
Request request2 = new Request();
request2.setRequestType("请假");
request2.setRequestConten("李雷请假");
request2.setNumber(4);
cm.requestApplication(request2);
Request request3 = new Request();
request3.setRequestType("加薪");
request3.setRequestConten("李雷请求加薪");
request3.setNumber(500);
cm.requestApplication(request3);
Request request4 = new Request();
request4.setRequestType("加薪");
request4.setRequestConten("李雷请求加薪");
request4.setNumber(1000);
cm.requestApplication(request4);
}
}
e.输出结果
经理:李雷请假1天被批准
总监:李雷请假4天被批准
总经理:李雷请求加薪500被批准
总经理:李雷请求加薪1000再说吧