设计模式之责任链模式
责任链模式的定义:Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.(使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理该请求为止)
责任链模式的重点在“链”上,由一条链去处理相似的请求在链中决定谁来处理这个请求,并返回相应的结果。“链”是由多个处理者CpncreteHandler组成的。
通用类图
通用代码
抽象处理者
public abstract class Handler {
private Handler nextHandler;
public final Response handlMessage(Request request){
Response response=null;
if(this.getHandlerLevel().equals(request.getRequestLevel())){
response=this.echo(request);
}else{
if(this.nextHandler!=null){
response=this.nextHandler.handleMessage(request);
}else{
}
}
return response;
}
public void setNext(Handler _handler){
this.nextHandler=_handler;
}
protected abstract Level getHandlerLevel();
protected abstract Response echo(Request request);
}
具体处理者
public class ConcreteHandler1 extends Handler{
protected Response echo(Request request){
return null;
}
protected Level getHandlerLevel(){
return null;
}
}
public class ConcreteHandler2 extends Handler{
protected Response echo(Request request){
return null;
}
protected Level getHandlerLevel(){
return null;
}
}
public class ConcreteHandler3 extends Handler{
protected Response echo(Request request){
return null;
}
protected Level getHandlerLevel(){
return null;
}
}
有关代码框架
public class Level {
}
public class Request {
public Level getRequestLevel(){
return null;
}
public class Response;
}
public class Response {
}
场景类
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
Handler handle1=new ConcreteHandler1();
Handler handle2=new ConcreteHandler2();
Handler handle3=new ConcreteHandler3();
handle1.setNext(handle2);
handle2.setNext(handle3);
Response response=handle1.handlMessage(new Request());
}
}
责任链模式的优点:将请求和处理分开,请求者可以不必知道是谁处理的,处理者可以不用知道请求的全貌,两者解耦,提高系统的灵活性。
责任链模式的缺点:一是性能问题,每个请求都是从链表头遍历到链表尾,特别是链表比较长的时候,性能是一个非常大的问题;二是调试不方便,特别是链表比较长,环节比较多的时候,由于采用了类似递归的方式,调试的时候可能逻辑比较复杂。
注意事项
链中节点的数量需要控制,避免出现超长链的情况,一般做法是在Handler中设置一个最大的节点数量,在setNext()方法中判断是否已经是超过其阈值,超过则不允许建立,避免无意识的破坏系统性能。
例子:古代妇女三从四德
女性接口
public interface IWoman {
public int getType();
public String getRequest();
}
古代妇女
public class Women implements IWoman{
private int type=0;
private String request="";
public Women(int _type,String _request){
this.type=_type;
switch(this.type){
case 1:
this.request="女儿的请求是:"+_request;
break;
case 2:
this.request="妻子的请求是:"+_request;
break;
case 3:
this.request="母亲的请求是:"+_request;
break;
}
}
public int getType(){
return this.type;
}
public String getRequest(){
return this.request;
}
}
Handler类
public abstract class Handler {
public final static int FATHER_LEVEL_REQUEST=1;
public final static int HUSBAND_LEVEL_REQUEST=1;
public final static int SON_LEVEL_REQUEST=1;
private int level=0;
private Handler nextHandler;
public Handler(int _level){
this.level=_level;
}
public final void HandleMessage(IWoman woman){
if(woman.getType()==this.level){
this.response(woman);
}else{
if(this.nextHandler!=null){
this.nextHandler.HandleMessage(woman);
}else{
System.out.println("没地方请示了");
}
}
}
public void setNext(Handler _handler){
this.nextHandler=_handler;
}
protected abstract void response(IWoman woman);
}
父亲类
public class Father extends Handler{
public Father(){
super(Handler.FATHER_LEVEL_REQUEST);
}
protected void response(IWoman woman){
System.out.println("向父亲请示");
System.out.println(woman.getRequest());
System.out.println("父亲同意");
}
}
丈夫类
public class Husband extends Handler{
public Husband(){
super(Handler.HUSBAND_LEVEL_REQUEST);
}
protected void response(IWoman woman){
System.out.println("向丈夫请示");
System.out.println(woman.getRequest());
System.out.println("丈夫同意");
}
}
儿子类
public class Son extends Handler{
public Son(){
super(Handler.SON_LEVEL_REQUEST);
}
protected void response(IWoman woman){
System.out.println("向儿子请示");
System.out.println(woman.getRequest());
System.out.println("儿子同意");
}
}
场景类
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
Random rand=new Random();
ArrayList<IWoman> arrayList=new ArrayList();
for(int i=0;i<5;++i){
arrayList.add(new Women(rand.nextInt(4),"我要逛街"));
}
Handler father=new Father();
Handler husband=new Husband();
Handler son=new Son();
father.setNext(husband);
husband.setNext(son);
for(IWoman women:arrayList){
father.HandleMessage(women);
}
}
}