Java设计模式12——责任链模式

转:http://blog.youkuaiyun.com/xu__cg/article/details/53069998

一、定义


 

责任链是每一个对象持有其下家的引用而形成的一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织和分配责任。

 角色:

     抽象处理者:抽象的处理者实现三个职责:一是定义一个请求的处理方法,唯一对外开放的方法;二是定义一个链的编排方法,设置下一个处理者;三是定义了具体的请求者必须实现的方法(子类可以通过实现这个方法来实现自己的业务逻辑)。

     具体的处理者:继承抽象处理者,实现各自处理请求的业务逻辑方法
 

        

二、场景举例


 责任链模式屏蔽了请求的处理过程,你发起一个请求到底是谁处理的,这个你不用关心,只要你把请求抛给责任链的第一个处理者,最终会返回一个处理结果(当然也可以不做任何处理),作为请求者可以不用知道到底是需要谁来处理的,这是责任链模式的核心.

1.责任链模式也可以作为一种补救模式来使用。举个简单例子,如项目开发的时候,需求确认是这样的:一个请求(如银行客户存款的币种),一个处理者(只处理人民币),但是随着业务的发展(改革开放了嘛,还要处理美元、日元等),处理者的数量和类型都有所增加,那这时候就可以在第一个处理者后面建立一个链,也就是责任链来处理请求,如果是人民币,好,还是第一个业务逻辑来处理;如果是美元,好,传递到第二个业务逻辑来处理;日元、欧元……这些都不用在对原有的业务逻辑产生很大改变,通过扩展实现类就可以很好地解决这些需求变更的问题。

2.生活中场景 
在学校时,请假条的审批过程:

  • 如果请假小于3天,辅导员直接批准。
  • 如果请假大于等于3天小于10天,需院长审批。
  • 如果请假大于等于10天小于30天,校长审批。
  • 请假被拒绝

3.开发中场景 
  Java中,异常机制就是一种责任链模式。一个try可以对应多个catch,当第一个catch不匹配时,则自动跳到第二个catch。

上述就是一个责任链,各级对象都有处理请求能力但处理能力不同,请求一直沿着责任链传递下去。

 

三、模式结构


  • Requester请求者:请求类。
  • AbstractHandler抽象处理者:由于各级对象都具有相同的处理能力,所以有一个公共的抽象父接口。(拥有下一个处理者成员字段nextHandler,拥有设置下一个处理者成员函数setNext(AbstractHandler))
  • ConcreteHandler具体处理者:具有不同处理能力的处理类。

代码示例: 
Requester请求者:

/**
 * 请求者发出请假:学生类
 */
public class Student {
    private String name;
    private int leaveDays;
    private String reason;
    public Student(String name, int leaveDays, String reason) {
        super();
        this.name = name;
        this.leaveDays = leaveDays;
        this.reason = reason;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getLeaveDays() {
        return leaveDays;
    }
    public void setLeaveDays(int leaveDays) {
        this.leaveDays = leaveDays;
    }
}

 

AbstractHandler抽象处理者:

/**
 * 抽象处理者:领导类
 */
public abstract class Leader {
    protected String name;
    protected Leader nextHandler;//关键,责任链上的后继对象
    public Leader(String name) {
        super();
        this.name = name;
    }

    //关键,设定责任链上的后继对象
    public void setNextHandler(Leader nextHandler) {
        this.nextHandler = nextHandler;
    }

    // 关键,处理请求的核心的业务方法
    protected abstract void handleRequest(Student student);

}

 

ConcreteHandler抽象处理者:

/**
 * 具体处理者:辅导员类
 */
public class Assistant extends Leader {

    public Assistant(String name) {
        super(name);
    }

    @Override
    protected void handleRequest(Student student) {
        if(student.getLeaveDays()<3){
            System.out.println("辅导员:"+this.name+"批准"+student.getName()+"的请假");
        }else{
            if(this.nextHandler!=null){
                this.nextHandler.handleRequest(student);
            }
        }
    }
}



/**
 * 具体处理者:院长类
 */
public class Dean extends Leader {

    public Dean(String name) {
        super(name);
    }

    @Override
    protected void handleRequest(Student student) {
        if(student.getLeaveDays()<10){
            System.out.println("院长:"+this.name+"批准"+student.getName()+"的请假");
        }else{
            if(this.nextHandler!=null){
                this.nextHandler.handleRequest(student);
            }       
        }
    }
}

/**
 * 具体处理者:校长类
 */
public class HeadMaster extends Leader {

    public HeadMaster(String name) {
        super(name);
    }

    @Override
    protected void handleRequest(Student student) {
        if(student.getLeaveDays()<30){
            System.out.println("校长:"+this.name+"批准"+student.getName()+"的请假");
        }else{
            System.out.println("请假被拒绝");    
        }
    }
}

 

客户端:

public class Client {

    public static void main(String[] args) {
        Leader assistant=new Assistant("张三");
        Leader dean=new Dean("李四");
        Leader headMaster=new HeadMaster("王五");
        //组织责任链对象的关系
        assistant.setNextHandler(dean);
        dean.setNextHandler(headMaster);

        //开始请假操作
        Student student=new Student("赵六",15,"回家探亲");
        assistant.handleRequest(student);
    }
}

 

UML类图: 
这里写图片描述

四、非链表实现责任链


上述代码通过链表的方式定义责任链,而往往通过集合、数组生成责任链更加实用。实际上,在很多项目中,每个具体的Handler并不是由开发团队定义的,而是项目上线后由外部单位追加的,所以使用链表方式定义COR链就很困难。

五、总结


使用场景要求: 

  1. 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定;
  2. 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求;
  3. 处理一个请求的对象集合应被动态指定。

优点

  1. 实现了请求者与处理者代码分离。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求。因此客户端与处理者之间的耦合程度降低。客户端不必在代码中加入复杂的if-else语句。
  2. 责任链对象之间的耦合程度低。责任链上多个的对象处理请求的代码分离,互不影响。
  3. 灵活性大大提高。每个责任链对象可以动态的分配下家。

缺点: 

  1. 性能问题,每个请求都是从链头遍历到链尾,特别是在链比较长的时候,性能是一个非常大的问题。
  2. 调试不方便,特别是链条比较长,环节比较多的时候,由于采用了类似递归的方式,调试的时候逻辑可能比较复杂。

职责链模式对于请求的处理是不知道最终处理者是谁,所以是运行动态寻找并指定;而命令模式中对于命令的处理时在创建命令是已经显式或隐式绑定了接收者。

使用责任链模式的注意事项:

链中节点数量需要控制,避免出现超长链的情况,一般的做法是在Handler中设置一个最大节点数量,在setNext方法中判断是否已经是超过其阈值,超过则不允许该链建立,避免无意识地破坏系统性能。

 

Android源码中的责任链模式

 1.View事件的分发处理

  ViewGroup事件投递的递归调用就类似于一条责任链,一旦其寻找到责任者,那么将由责任者持有并消费掉该次事件,具体体现在View的onTouchEvent方法中返回值的设置,如果返回false,那么意味着当前的View不会是该次的责任人,将不会对其持有;如果返回true,此时View会持有该事件并不再向外传递。 
  

2. 广播
 

 

实例2:

Request类  可以封装请求数据到此对象

/**
 * 请求信息类
 * @author zqkj001
 *
 */
public class Request {
    
	//请求等级
	private int requestLevel;
 
	public int getRequestLevel() {
		return requestLevel;
	}
 
	public void setRequestLevel(int requestLevel) {
		this.requestLevel = requestLevel;
	}	

Response类  接收处理结果信息

/**
 * 处理结果信息类
 * @author zqkj001
 *
 */
public class Response {
   
	private String result;
 
	public Response(String re) {
 
		this.result=re;
	
	}
	
	public String getResult() {
		return result;
	}
	
}

Handler类  抽象处理者类

public abstract class Handler {
   
	//定义下一级处理器,若自己不能处理则转给下一级
	private Handler nextHandler;
	
	//每一个handler都要对请求做处理(模板方法模式的模板方法)
	public final Response handRequest(Request request){
		Response response=null;
		//判断是否属于自己的处理级别,如果不是则转给下一级
		if(this.getHandlerLevel()==request.getRequestLevel()){
			response=this.doRequest(request);
		}else{
			if (this.nextHandler!=null) {	
				response=this.nextHandler.handRequest(request);
			}else{
				response=new Response("无合适的处理者,退出");
			}
		}
		return response;		
	}
	
	//设置下一级处理器
	public void setNextHandler(Handler handler){
		this.nextHandler=handler;
	}
	
	//每一个处理器都有一个处理级别(模板方法的基本方法)
	protected abstract int getHandlerLevel();
	
	//每一个处理器自己的请求处理逻辑(模板方法的基本方法)
	protected abstract Response doRequest(Request request);
		
}

Handler1、Handler2、Handler3  具体处理者类


public class MyHandler1 extends Handler {
    
	private final int level1=1;
	
	@Override
	protected int getHandlerLevel() {
		return this.level1;
	}
 
	@Override
	protected Response doRequest(Request request) {
		return new Response("handler1 execute success");
	} 
}

public class MyHandler2 extends Handler {
	
	private final int level2=2;
	
	@Override
	protected int getHandlerLevel() {
		
		return this.level2;
		
	}
 
	@Override
	protected Response doRequest(Request request) {
		return new Response("handler2 execute success");
	}
}

public class MyHandler3 extends Handler {
	private final int level3=3;
	
	@Override
	protected int getHandlerLevel() {
		return this.level3;
	}
 
	@Override
	protected Response doRequest(Request request) {
		return new Response("handler3 execute success");
	}
 
}

测试类:

public class Test {
    
	public static void main(String[] args) {
		
		//声明所有的处理节点
		Handler handler1=new MyHandler1();
		Handler handler2=new MyHandler2();
		Handler handler3=new MyHandler3();
		
		//设置链中的责任顺序 1-2-3
		handler1.setNextHandler(handler2);
        handler2.setNextHandler(handler3);
        
        //构造请求信息
        Request request=new Request();
        request.setRequestLevel(3);
        
        //提交请求,返回结果
        Response response=handler1.handRequest(request);
		System.out.println(response.getResult());
	}	
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值