设计模式笔记--责任链模式

news/2024/5/19 13:45:02 标签: 设计模式, 责任链模式

常用设计模式有23中,分为:

创建型模式(主要用于创建对象)

1、单例模式    2、工厂方法模式    3、抽象工厂模式    4、建造者模式     5、原型模式 
行为型模式 (主要用于描述对象或类是怎样交互和怎样分配职责)

1、模板方法模式  2、中介者模式  3、命令模式    4、责任链模式   5、策略模式   6、迭代器模式  

7、观察者模式      8、备忘录模式   9、访问者模式   10、状态模式   11、解释器模式

结构型模式(主要用于处理类或对象的组合)

1、代理模式  2、装饰模式   3、适配器模式   4、组合模式   5、外观模式(门面模式)   6、享元模式    7、桥梁模式




责任链模式定义如下: 

使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。 
 
责任链模式的重点是在“链”上,由一条链去处理相似的请求在链中决定谁来处理这个请求,并返回相应的结果  




责任链模式的核心在“链”上,“链”是由多个处理者ConcreteHandler组成的。抽象Handler类  
<span style="font-size:18px;">代码清单16-14 抽象处理者
public abstract class Handler {
private Handler nextHandler;
//每个处理者都必须对请求做出处理
public final Response handleMessage(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);
}</span>

抽象的处理者实现三个职责:
一是定义一个请求的处理方法handleMessage,唯一对外开放的方法;
二是定义一个链的编排方法setNext,设置下一个处理者;
三是定义了具体的请求者必须实现的两个方法:定义自己能够处理的级别getHandlerLevel和具体的处理任务echo  

注意 在责任链模式中一个请求发送到链中后,前一节点消费部分消息,然后交由后续节点继续处理,最终可以有处理结果也可以没有处理结果,读者可以不用理会什么纯的、不纯的责任链模式。同时,请读者注意handlerMessage方法前的final关键字,可以阅读第10章的模板方法模式。  


我们定义三个具体的处理者,以便可以组成一个链  
<span style="font-size:18px;">代码清单16-15 具体处理者
public class ConcreteHandler1 extends Handler {
//定义自己的处理逻辑
protected Response echo(Request request) {
//完成处理逻辑
return null;
}
//设置自己的处理级别
protected Level getHandlerLevel() {
//设置自己的处理级别
return null;
}
}

</span>
<span style="font-size:18px;">public class ConcreteHandler2 extends Handler {
//定义自己的处理逻辑
protected Response echo(Request request) {
//完成处理逻辑
return null;
}
//设置自己的处理级别
protected Level getHandlerLevel() {
//设置自己的处理级别
return null;
}
}

</span>
<span style="font-size:18px;">public class ConcreteHandler3 extends Handler {
//定义自己的处理逻辑
protected Response echo(Request request) {
//完成处理逻辑
return null;
}
//设置自己的处理级别
protected Level getHandlerLevel() {
//设置自己的处理级别
return null;
}
}</span>


在处理者中涉及三个类:Level类负责定义请求和处理级别,Request类负责封装请 求,Response负责封装链中返回的结果,该三个类都需要根据业务产生   ,其框架代码如代码清单16-16所示。   
<span style="font-size:18px;">代码清单16-16 模式中有关框架代码
public class Level {
//定义一个请求和处理等级
}

</span>
<span style="font-size:18px;">public class Request {
//请求的等级
public Level getRequestLevel(){
return null;
}}</span>
<span style="font-size:18px;">public class Response {
//处理者返回的数据
}</span>


在场景类或高层模块中对链进行组装,并传递请求,返回结果,如代码清单16-17所示。  
<span style="font-size:18px;">代码清单16-17 场景类
public class Client {
public static void main(String[] args) {
//声明所有的处理节点
Handler handler1 = new ConcreteHandler1();
Handler handler2 = new ConcreteHandler2();
Handler handler3 = new ConcreteHandler3();
//设置链中的阶段顺序1-->2-->3
handler1.setNext(handler2);
handler2.setNext(handler3);
//提交请求,返回结果
Response response = handler1.handlerMessage(new Request());
}
}</span>

在实际应用中,一般会有一个封装类对责任模式进行封装,也就是替代Client类,直接返回链中的第一个处理者,具体链的设置不需要高层次模块关系,这样,更简化了高层次模块的调用,减少模块间的耦合,提高系统的灵活性。  
 

实例 “ 三从”(“未嫁从父、既嫁从夫、夫死从子”)  





从类图上看,三个实现类Father、Husband、Son只要实现构造函数和父类中的抽象方法response就可以了,具体由谁处理女性提出的请求,都已经转移到了Handler抽象类中

Handler怎么实现,如代码清单16-8所示。
<span style="font-size:18px;">代码清单16-8 修改后的Handler类
public abstract class Handler {
public final static int FATHER_LEVEL_REQUEST = 1;
public final static int HUSBAND_LEVEL_REQUEST = 2;
public final static int SON_LEVEL_REQUEST = 3;
//能处理的级别
private int level =0;
//责任传递,下一个人责任人是谁
private Handler nextHandler;
//每个类都要说明一下自己能处理哪些请求
public Handler(int _level){
this.level = _level;
}
//一个女性(女儿、妻子或者是母亲)要求逛街,你要处理这个请求
public final void HandleMessage(IWomen women){
if(women.getType() == this.level){
this.response(women);
}else{
if(this.nextHandler != null){ //有后续环节,才把请求往后递送
this.nextHandler.HandleMessage(women);
}else{ //已经没有后续处理人了,不用处理了
System.out.println("---没地方请示了,按不同意处理---\n");
}
}
}
/*
* 如果不属于你处理的请求,你应该让她找下一个环节的人,如女儿出嫁了,
* 还向父亲请示是否可以逛街,那父亲就应该告诉女儿,应该找丈夫请示
*/
public void setNext(Handler _handler){
this.nextHandler = _handler;
}
//有请示那当然要回应
protected abstract void response(IWomen women);
}</span>
在这里也用到模板方法模式,在模板方法中判断请求的级别和当前能够处理的级别,如果相同则调用基本方法,做出反馈;如果不相等,则传递到下一个环节,由下一环节做出回应,如果已经达到环节结尾,则直接做不同意处理。
基本方法response需要各个实现类实现,每个实现类只要实现两个职责:一是定义自己能够处理的等级级别;二是对请求做出回应,


首节点Father类,如代码清单16-9所示。
<span style="font-size:18px;">代码清单16-9 父亲类
public class Father extends Handler {
//父亲只处理女儿的请求
public Father(){
super(Handler.FATHER_LEVEL_REQUEST);
}
//父亲的答复
protected void response(IWomen women) {
System.out.println("--------女儿向父亲请示-------");
System.out.println(women.getRequest());
System.out.println("父亲的答复是:同意\n");
}
}</span>


丈夫类定义自己能处理的等级为2的请示,如代码清单16-10所示。
<span style="font-size:18px;">代码清单16-10 丈夫类
public class Husband extends Handler {
//丈夫只处理妻子的请求
public Husband(){
super(Handler.HUSBAND_LEVEL_REQUEST);
}
//丈夫请示的答复
protected void response(IWomen women) {
System.out.println("--------妻子向丈夫请示-------");
System.out.println(women.getRequest());
System.out.println("丈夫的答复是:同意\n");
}
}</span>


儿子类只能处理等级为3的请示,如代码清单16-11所示。
<span style="font-size:18px;">代码清单16-11 儿子类
public class Son extends Handler {
//儿子只处理母亲的请求
public Son(){
super(Handler.SON_LEVEL_REQUEST);
}
//儿子的答复
protected void response(IWomen women) {
System.out.println("--------母亲向儿子请示-------");
System.out.println(women.getRequest());
System.out.println("儿子的答复是:同意\n");
}
}</span>
构造方法是必须实现的,父类框定子类必须有一个显式构造函数,子类不实现编译不通过。通过构造方法我们设置了各个类能处理的请求类型,Father只能处理请求类型为1(也就是女儿)的请求;Husband只能处理请求类型类为2(也就是妻子)的请求,儿子只能处理请求类型为3(也就是母亲)的请求,那如果请求类型为4的该如何处理呢?在Handler中我们已经判断了,如何没有相应的处理者(也就是没有下一环节),则视为不同意。


Women类的接口 
<span style="font-size:18px;">public interface IWomen {
//获得个人状况
public int getType();
//获得个人请示,你要干什么?出去逛街?约会?还是看电影?
public String getRequest();
}</span>


实现类,如代码清单16-12所示。
<span style="font-size:18px;">代码清单16-12 女性类
public class Women implements IWomen{
/*
* 通过一个int类型的参数来描述妇女的个人状况
* 1--未出嫁
* 2--出嫁
* 3--夫死
*/
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;
}
}
//获得自己的状况
public int getType(){
return this.type;
}
//获得妇女的请求
public String getRequest(){
return this.request;
}
}</span>


我们再来看Client类是怎么描述古代这一个礼节的,如代码清单16-13所示。
<span style="font-size:18px;">代码清单16-13 场景类
public class Client {
public static void main(String[] args) {
//随机挑选几个女性
Random rand = new Random();
ArrayList 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(IWomen women:arrayList){
father.HandleMessage(women);
}
}
}  </span>
 

优点  

责任链模式非常显著的优点是将请求和处理分开  


缺点  

一是性能问题 ,每个请求都是从链头遍历到链尾,特别是在链比较长的时候,性能是一个非常大的问题 

二是调试不很方便  ,由于采用了类似递归的方式,调试的时候逻辑可能比较复杂  


注意事项   

链中节点数量需要控制,避免出现超长链的情况


在例子和通用源码中Handler是抽象类,融合了模板方法模式,每个实现类只要实现两个方法:echo方法处理请求和getHandlerLevel获得处理级别,

想想单一职责原则和迪米特法则吧,通过融合模板方法模式,各个实现类只要关注的自己业务逻辑就成了,至于说什么事要自己处理,那就让父类去决定好了,也就是说父类实现了请求传递的功能,子类实现请求的处理,符合单一职责原则,各个实现类只完成一个动作或逻辑,也就是只有一个原因引起类的改变,

我建议大家在使用的时候用这种方法,好处是非常明显的了,子类的实现非常简单,责任链的建立也是非常灵活的。  




http://www.niftyadmin.cn/n/1678235.html

相关文章

手机产品交互设计样式

很多人都说&#xff0c;手机产品交互限制因素很多&#xff0c;过小的屏幕分辨率&#xff0c;过低的系统性能&#xff0c;过慢的网速&#xff0c;过弱的电池续航能力等等。但是在限制中还能做出优秀的设计&#xff0c;才显得弥足珍贵&#xff0c;就像风靡Symbian平台的gravity一…

学了这个,不怕项目没有好的图表展示

学了Highcharts&#xff0c;不怕项目没有好的图表展示一、Highcharts了解1、Highcharts介绍2、特点3、图表类型二、Highcharts环境配置1、安装jQuery2、安装Highcharts三、Highcharts配置语法1、创建HTML页面2、创建配置文件3、创建json数据四、实例展示&#xff08;曲线图&…

设计模式笔记--装饰模式

常用设计模式有23中&#xff0c;分为&#xff1a; 创建型模式&#xff08;主要用于创建对象&#xff09; 1、单例模式 2、工厂方法模式 3、抽象工厂模式 4、建造者模式 5、原型模式 行为型模式 &#xff08;主要用于描述对象或类是怎样交互和怎样分配职责&…

祝各位朋友元旦快乐,新年大发!!!

Ladies & Gentlemen, 谢谢各位一年来对我的支持和帮助&#xff0c;祝各位元旦快乐&#xff0c;新年大发&#xff01;&#xff01;&#xff01;转载于:https://blog.51cto.com/patterson/469835

Highcharts之配置说明

Highcharts配置选项详细说明一、参数了解&#xff08;属性事件&#xff09;1、Chart&#xff1a;图表区选项2、Color&#xff1a;颜色选项3、Title&#xff1a;标题选项4、xAxis&#xff1a;X轴选项5、Series&#xff1a;数据列选项6、plotOptions&#xff1a;数据点选项7、Too…

设计模式笔记--策略模式

常用设计模式有23中&#xff0c;分为&#xff1a; 创建型模式&#xff08;主要用于创建对象&#xff09; 1、单例模式 2、工厂方法模式 3、抽象工厂模式 4、建造者模式 5、原型模式 行为型模式 &#xff08;主要用于描述对象或类是怎样交互和怎样分配职责&…

双向(端)链表、栈、队列

双端链表 双端栈 双端队列 从实用角度,感受不出双端队列的好处,但其可以充当栈和队列的角色. 参考资料:http://baike.baidu.com/view/1627726.htm Test static void Main() {var deque new Deque<int>();Console.WriteLine("Stack:");//stackdeque.AddFirst(1…

设计模式笔记--适配器模式

常用设计模式有23中&#xff0c;分为&#xff1a; 创建型模式&#xff08;主要用于创建对象&#xff09; 1、单例模式 2、工厂方法模式 3、抽象工厂模式 4、建造者模式 5、原型模式 行为型模式 &#xff08;主要用于描述对象或类是怎样交互和怎样分配职责&…