1.责任链模式
顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。责任链模式是一种对象的行为模式。在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。
责任链模式中的三个角色:
Handler处理者
抽象处理者(Handler)角色:定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。上图中Handler类的聚合关系给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作。在实例中对应的是,Leader类和getAccount
concreteHandler(具体的处理者)
具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。在此实例中,由director,manager角色和其他几个类扮演
Client
请求者角色,就是向第一个具体的handler发送请求的角色,并连接好责任链,实例中对应的是Client类的main方法。
责任链模式图:
责任链模式实例代码如下,举得例子是公司员工出差报销实例:首先,先定义一个请求类,定义员工的基本信息,代码如下:
//get和set的方法省略
public class Request {
private String name; //姓名
private double money; //报销金额
private String reason;
public Request(String name, double money, String reason) {
super();
this.name = name;
this.money = money;
this.reason = reason;
}
}
其次,定义一个抽象的处理者领导,不同的领导能够分配的报销金额不同,代码如下:
public abstract class Leader {
protected String name;//领导名字
protected Leader leader;//定义下一个责任领导
public Leader(String name){
this.name = name;
}
public void nextLeader(Leader leader){
this.leader = leader;
}
public abstract void getAccount(Request request); //报销请求
}
最后,用具体的处理者继承抽象具体者,并实现其中报销的简单业务。代码如下:
//直接领导
public class DirectLeader extends Leader{
public DirectLeader(String name) {
super(name);
}
@Override
public void getAccount(Request request) {
String name = request.getName();
double account = request.getMoney();
String reason = request.getReason();
if(account<=500){
System.out.println("员工姓名"+name+",报销金额是:"+account+"。原因是:"+reason);
System.out.println("领导:"+this.name+",审批通过");
}else{
System.out.println("报销金额过多,无法处理。转到经理");
if(this.leader!=null){
this.leader.getAccount(request);
}
}
}
}
//经理
public class Manger extends Leader{
public Manger(String name) {
super(name);
// TODO Auto-generated constructor stub
}
@Override
public void getAccount(Request request) {
String name = request.getName();
double account = request.getMoney();
String reason = request.getReason();
if(account<=1000){
System.out.println("员工姓名"+name+",报销金额是:"+account+"。原因是:"+reason);
System.out.println("领导:"+this.name+",审批通过");
}else{
System.out.println("报销金额过多,无法处理。转到总经理");
if(this.leader!=null){
System.out.println(this.leader);
this.leader.getAccount(request);
}
}
}
}
//总经理
public class General extends Leader{
public General(String name) {
super(name);
// TODO Auto-generated constructor stub
}
@Override
public void getAccount(Request request) {
String name = request.getName();
double account = request.getMoney();
String reason = request.getReason();
if(account<=5000){
System.out.println("员工姓名"+name+",报销金额是:"+account+"。原因是:"+reason);
System.out.println("领导:"+this.name+",审批通过");
}else{
System.out.println("报销金额过多,无法处理");
if(this.leader!=null){
this.leader.getAccount(request);
}
}
}
}
下面用客户端进行测试,代码如下:
public class Client {
public static void main(String[] args) {
Leader director = new DirectLeader("欧阳锋");
Leader manger = new Manger("黄药师");
Leader General = new General("王重阳");
//开始组织责任链
director.nextLeader(manger);
manger.nextLeader(General);
Request request = new Request("张三",2000,"住宿");
director.getAccount(request);
}
}
//运行结果
报销金额过多,无法处理。转到经理
员工姓名张三,报销金额是:2000.0。原因是:住宿
领导:黄药师,审批通过
.以上就是对责任链的简单理解,只要自己能处理就处理,不能处理就传给下一个责任者。
2.责任链模式优点和缺点
优点: 1、降低耦合度。它将请求的发送者和接收者解耦。 2、简化了对象。使得对象不需要知道链的结构。 3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。 4、增加新的请求处理类很方便。
缺点: 1、不能保证请求一定被接收。 2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。 3、可能不容易观察运行时的特征,有碍于除错。
3.应用场景
Tomcat中的Filter就是使用了责任链模式,创建一个Filter除了要在web.xml文件中做相应配置外,还需要实现javax.servlet.Filter接口。源码的抽象类里定义的方法,参考一下:
public Valve getNext();//返回下一个valve
public void setNext(Valve valve);//设置下一个valve
public void invoke(Request request, Response response)
throws IOException, ServletException;//invoke为实际要执行的代码
定义请求的几个方法,仅供参考。详细还要看下Tomcat源码。