java设计模式之责任链模式

职责链模式(Chain of Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

适用场景:

1、有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定;

2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求;

3、处理一个请求的对象集合应被动态指定。

通用类图:

通用例子:

先看看关系图:


Abstracthandler类提供了get和set方法,方便MyHandle类设置和修改引用对象,MyHandle类是核心,实例化后生成一系列相互持有的对象,构成一条链。

package com.deppon.tps.module.TestResponsibilityPattern;

public interface Handler {
	public void operator();
}
package com.deppon.tps.module.TestResponsibilityPattern;

public class AbstractHandler {
	private Handler handler;

	public Handler getHandler() {
		return handler;
	}
	public void setHandler(Handler handler) {
		this.handler = handler;
	}
}
package com.deppon.tps.module.TestResponsibilityPattern;

public class MyHandler extends AbstractHandler implements Handler {
	private String name;
	public MyHandler(String name){
		this.name=name;
	}
	@Override
	public void operator() {
		System.out.println(name+"handed!");
		if(getHandler()!=null){
			getHandler().operator();
		}
	}
}
package com.deppon.tps.module.TestResponsibilityPattern;

public class Test {
	public static void main(String[] args) {
		MyHandler h1=new MyHandler("张三");
		MyHandler h2=new MyHandler("李四");
		MyHandler h3=new MyHandler("王五");
		h1.setHandler(h2);
		h2.setHandler(h3);
		h1.operator();
	}
}

输出结果:


注意:链接上的请求可以是一条链,可以是一个树,还可以是一个环,模式本身不约束这个,需要我们自己去实现,同时,在一个时刻,命令只允许由一个对象传给另一个对象,而不允许传给多个对象。

实例2:

    在大学里面当班干部,时常要向上级申请各方面的东西。譬如申请全班外出秋游,普通同学将申请表交给班长,班长签字之后交给辅导员,辅导员批准之后上交到主任办公室…就是这样,一个请求(这里是一份申请表)有时候需要经过好几个级别的处理者(这里是辅导员、主任)的审查才能够最终被确定可行与否。

在这里表现出来的是一个职责链,即不同的处理者对同一个请求可能担负着不同的处理方式、权限,但是我们希望这个请求必须到达最终拍板的处理者(否则秋游就没戏了)。这种关系就很适合使用职责链模式了。

类图如下:


代码如下:

package com.deppon.tps.module.TestResponsibilityPattern.example;

public class Test {
	public static void main(String[] args) {
		// 创建请求并提交到指责链中进行处理 
		AbstractRequest request01=new Request01("请求-01");
		AbstractRequest request02=new Request02("请求-02");
		AbstractRequest request03=new Request03("请求-03");
		// 创建指责链的所有节点  
		AbstractHandler handler01=new Test().new Handler01();
		AbstractHandler handler02=new Test().new Handler02();
		AbstractHandler handler03=new Test().new Handler03();
		 // 进行链的组装,即头尾相连,一层套一层 
		handler01.setNextHandler(handler02);
		handler02.setNextHandler(handler03);
		// 每次提交都是从链头开始遍历  
		handler01.handleRequest(request01);
		handler01.handleRequest(request02);  
	    handler01.handleRequest(request03); 
	}

	//抽象请求类 
	 abstract class AbstractRequest {
		String content="";
		public  AbstractRequest(String content){
			this.content=content;
		}
		public  String getContent(){
			return content;
		}
		public abstract int getRequestLever();
	}
	//具体请求类01  
	public static  class Request01 extends  AbstractRequest{
		public Request01(String content) {
			new Test().super(content);
		}

		public int getRequestLever(){
			return 1;
		}
	}
	//具体请求类02  
	public static class Request02 extends AbstractRequest{
		public Request02(String content) {
			new Test().super(content);
		}
		public int getRequestLever(){
			return 2;
		}
	}
	//具体请求类03
	public static class Request03 extends AbstractRequest{
		public Request03(String content) {
			new Test().super(content);
		}
		public int getRequestLever(){
			return 3;
		}
	}
	
	//抽象处理类
	abstract class AbstractHandler {
		 // 责任链的下一个节点,即处理者 
		 private AbstractHandler nextHandler = null;  
		// 捕获具体请求并进行处理,或是将请求传递到责任链的下一级别  
		 public final void handleRequest(AbstractRequest request) { 
			// 若该请求与当前处理者的级别层次相对应,则由自己进行处理  
			 if(this.getHandlerLever()==request.getRequestLever()){
				 this.handlered(request);
			 }else{
				 // 当前处理者不能胜任,则传递至职责链的下一节点
				 if(nextHandler!=null){
					 System.out.println("当前处理者 0"+this.getHandlerLever()+"不足以处理请求 0"+request.getRequestLever());
					 // 这里使用了递归调用  
					 this.nextHandler.handleRequest(request);
				 }else{
					 System.out.println("职责链上的所有处理者都不能胜任该请求...");  
				 }
			 }
		 }
		 // 设置责任链中的下一个处理者  
		public void setNextHandler(AbstractHandler nextHandler) {
			this.nextHandler = nextHandler;
		}
		 // 获取当前处理者的级别  
		public int getHandlerLever(){
			return 0;
		 }
		 // 定义链中每个处理者具体的处理方式 
		 protected  abstract void handlered(AbstractRequest request);
	}
	
	class Handler01 extends AbstractHandler {
		public int getHandlerLever(){
			return 1;
		 }
		@Override
		protected void handlered(AbstractRequest request) {
			 System.out.println("处理者-01 处理 " + request.getContent() + "\n");  
		}
	}
	class Handler02 extends AbstractHandler {  
		public int getHandlerLever(){
			return 2;
		 }
		@Override
		protected void handlered(AbstractRequest request) {
			  System.out.println("处理者-02 处理 " + request.getContent()+ "\n");  
		}
	}
	class Handler03 extends AbstractHandler { 
		public int getHandlerLever(){
			return 3;
		 }
		@Override
		protected void handlered(AbstractRequest request) {
			 System.out.println("处理者-03 处理 " + request.getContent()+ "\n");  
		}
	}
}


在上面抽象处理者 AbstractHandler 类的 handleRequest() 方法中,被 protected 修饰,并且该方法中调用了两个必须被子类覆盖实现的抽象方法,这里是使用了模板方法模式(Template Mehtod)。其实在这里,抽象父类的 handleRequest() 具备了请求传递的功能,即对某些请求不能处理时,马上提交到下一结点(处理者)中,而每个具体的处理者仅仅完成了具体的处理逻辑,其他的都不用理。
 
记得第一次看到职责链模式的时候,我很惊讶于它能够把我们平时在代码中的 if..else.. 的语句块变成这样灵活、适应变化。例如:如果现在辅导员请长假了,但我们的秋游还是要争取申请成功呀,那么我们在 Client 类中可以不要创建 handler02,即不要将该处理者组装到职责链中。这样子处理比 if..else..好多了。或者说,突然来了个爱管闲事的领导,那么我照样可以将其组装到职责链中。
 
关于上面使用场景中提到的3个点:
1、处理者在运行时动态确定其实是我们在 Client 中组装的链所引起的,因为 具体的职责逻辑就在链中一一对应起来
2、因为不确定请求的具体处理者是谁,所以我们把所有可能的处理者组装成一条链,在遍历的过程中就相当于向每个处理者都提交了这个请求,等待其审查。并且在审查过程中,即使不是最终处理者,也可以进行一些请求的“包装”操作(这种功能类似于装饰者模式),例如上面例子中的签名批准;
3、处理者集合的动态指定跟上面的第1、2点类似,即在 Client 类中创建了所有可能的处理者。
 
不足之处:

1、对于每一个请求都需要遍历职责链,性能是个问题

2、抽象处理者 AbstractHandler 类中的 handleRequest() 方法中使用了递归,栈空间的大小也是个问题

 个人看法:

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

适用场景:

§ 场景1

       手机平台系统常有提供对手机日程、电话、短信、通话记录等信息的备份,通常应用平台会提供可选择备份项的UI给用户,变化部分主要有以下几点:

1、 系统增加或删除备份项目

2、 用户可选择备份、还原项不固定,致使应用无法良性的判断该执行哪些备份


代码示例:

http://download.csdn.net/download/webwalker/7470265

§ 场景2

类似Work flow中面向流程性的处理方案也是一个很好的选择,关于WF这里不在赘述。在面向这种流程性事务处理过程中,简单的说就是你有很多业务,这些业务都有各自的业务处理流程,且这些流程有很多相同的事务处理逻辑,则大可通过将每个主要的业务流程作为一个处理Step、一个链节点,通过配置链节点的先后顺序,来完成一系列业务逻辑的执行过程。而各个节点或事务step可通过上下文实现数据共享与串联(对链中各环节存有共性、异性的地方进行变化封装,而后与主链进行衔接)。

 

§ 场景3

       增值业务中,常有提供规则设置UI给使用者,以便使用者可以委托付款周期、自动充值(按天、按周、按月、按年、按小时)、自动提现等,当然每部分需采用不同的算法策略。在此基础上,主要的变化部分如下:

1、 每个商户可设置的规则类型不固定

2、 每个商户可设置的规则个数不固定

3、 每个商户设置的时间点不固定

通过链接的方式完成不同过则的自动匹配与处理较佳!






  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值