本文目录
顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。
在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
一、责任链模式介绍
意图:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。
主要解决:职责链上的处理者负责处理请求,客户只需要将请求发送到职责链上即可,无须关心请求的处理细节和请求的传递,所以职责链将请求的发送者和请求的处理者解耦了。
何时使用:在处理消息的时候以过滤很多道。
如何解决:拦截的类都实现统一接口。
关键代码:Handler 里面聚合它自己,在 HandlerRequest 里判断是否合适,如果没达到条件则向下传递,向谁传递之前 set 进去。
应用实例: 1、红楼梦中的"击鼓传花"。 2、JS 中的事件冒泡。 3、JAVA WEB 中 Apache Tomcat 对 Encoding 的处理,Struts2 的拦截器,jsp servlet 的 Filter。
优点: 1、降低耦合度。它将请求的发送者和接收者解耦。 2、简化了对象。使得对象不需要知道链的结构。 3、增强给对象指派职责的灵活性。通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任。 4、增加新的请求处理类很方便。
缺点: 1、不能保证请求一定被接收。 2、系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用。 3、可能不容易观察运行时的特征,有碍于除错。
使用场景: 1、有多个对象可以处理同一个请求,具体哪个对象处理该请求由运行时刻自动确定。 2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。 3、可动态指定一组对象处理请求。
注意事项:在 JAVA WEB 中遇到很多应用。
二、代码实现
所有设计模式的代码实现例子都可在码云上查看哦,感兴趣的可以查看哈,码云地址:https://gitee.com/no8g/java-design-patterns
2.1 业务逻辑
中国古代对妇女制定了“三从四德”的道德规范,“三从”是指“未嫁从父、既嫁从夫、夫死从子”,也就是说一个女性,在没有结婚的时候要听从于父亲,结了婚后听从于丈夫,丈夫死了还要听儿子的。举个例子来说,一个女的要出去逛街,同样这样的一个请求,在她没有出嫁前她必须征得父亲的同意,出嫁之后必须获得丈夫的许可,那丈夫死了怎么办?一般都是男的比女的死的早,还要问问儿子是否允许自己出去逛街,估计你下边马上要问要是没有儿子怎么办?请示小叔子、侄子等等。在父系社会中,妇女只占从属地位,现在想想中国的妇女还是比较悲惨的,逛个街还要请示来请示去,而且作为父亲、丈夫、儿子只有两种选择:要不承担起责任来告诉她允许或不允许逛街,要不就让她请示下一个人,这是整个社会体系的约束。
应用到我们项目中就是业务规则,那我们来看怎么把“三从”通过我们的程序来实现,需求很简单:通过程序描述一下古代妇女的“三从”制度,好我们先看类图:
我们可以抽象成这样一个结构,女性的请求先发送到父亲类,父亲类一看是自己要处理的,就回应处理,如果女儿已经出嫁了,那就要把这个请求转发到女婿来处理,那女婿一旦去天国报道了,那就由儿子来处理这个请求,类似于这样请求:
父亲、丈夫、儿子每个节点有两个选择:要么承担责任,做出回复;要么把请求转发到后序环节。结构分析的已经很清楚了,那我们看怎么来实现这个功能,先看类图:
从类图上看,三个实现类 Father、Husband、Son 只要实现构造函数和父类的中抽象方法就可以了,具体怎么处理这些请求,都已经转移到了 Hanlder 抽象类中,我们来看 Hanlder 怎么实现:
结果也正确,业务调用类 Client 也不用去做判断到底是需要谁去处理,而且 Handler 抽象类的子类以后可以继续增加下去,只是我们这个传递链增加而已,调用类可以不用了解变化过程,甚至是谁在处理这个请求都不用知道。
以上讲解的就是责任链模式,你看 Father、Husband、Son 这三个类的处理女性的请求时是不是在传递呀,每个环节只有两个选项:要么承担责任做出回应,要么向下传递请求,最终会有环节做出回应,通用类图如下:
2.2 代码实现
package com.iot.practice.designpattern.chainofresponsibility.chainofresponsibilitypattern;
import com.iot.practice.designpattern.chainofresponsibility.IWomen;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* <p>Client 此类用于:</p>
* <p>@author:hujm</p>
* <p>@date:2021年02月19日 11:37</p>
* <p>@remark:</p>
*/
public class ChainOfResponsibilityClient {
public static void main(String[] args) {
// 随机挑选几个女性
Random random = new Random();
List<IWomen> iWomenList = new ArrayList<>();
for (int i = 0; i < 5; i++) {
iWomenList.add(new IWomenImpl(random.nextInt(4), "我要看电影"));
}
// 定义三个请示对象
Handler father = new Father();
Handler husband = new Husband();
Handler son = new Son();
// 设置请示顺序
father.setNext(husband);
husband.setNext(son);
for (IWomen iWomen : iWomenList) {
father.HandleMessage(iWomen);
}
}
}
package com.iot.practice.designpattern.chainofresponsibility.chainofresponsibilitypattern;
import com.iot.practice.designpattern.chainofresponsibility.IWomen;
/**
* <p>Handler 此类用于:</p>
* <p>@author:hujm</p>
* <p>@date:2021年02月19日 10:56</p>
* <p>@remark:
* 有没有看到,其实在这里也用到模版方法模式,在模版方法中判断请求的级别和当前能够处理的级别,
* 如果相同则调用基本方法,做出反馈;如果不相等,则传递到下一个环节,由下一环节做出回应。基本方
* 法 response 要各个实现类都要实现,我们来看三个实现类:
* </p>
*/
public abstract class Handler {
/**
* 能处理的级别
*/
private int level = 0;
/**
* 责任传递,下一个人责任人是谁
*/
private Handler nextHandler;
/**
* 构造函数:每个类都要说明一下自己能处理哪些请求
*
* @param level 能处理的级别
*/
public Handler(int level) {
this.level = level;
}
/**
* 一个女性(女儿,妻子或者是母亲)要求逛街,你要处理这个请求
*
* @param iWomen 女性统称
*/
public final void HandleMessage(IWomen iWomen) {
if (iWomen.getType() == this.level) {
this.response(iWomen);
} else {
// 有后续环节,才把请求往后递送
if (this.nextHandler != null) {
this.nextHandler.HandleMessage(iWomen);
} else {
// /已经没有后续处理人了,不用处理了
System.out.println("-----------没地方请示了,不做处理!---------\n");
}
}
}
/**
* 如果不属于你处理的返回,你应该让她找下一个环节的人,比如
* 女儿出嫁了,还向父亲请示是否可以逛街,那父亲就应该告诉女儿,应该找丈夫请示
*
* @param handler 处理类
*/
public void setNext(Handler handler) {
this.nextHandler = handler;
}
/**
* 有请示那当然要回应
*
* @param iWomen 女性统称
*/
public abstract void response(IWomen iWomen);
}
package com.iot.practice.designpattern.chainofresponsibility;
/**
* <p>IWomen 此接口用于:</p>
* <p>@author:hujm</p>
* <p>@date:2021年02月19日 9:55</p>
* <p>@remark:古代悲哀女性的总称</p>
*/
public interface IWomen {
/**
* 获得个人状况
*
* @return 个人状况数值
*/
public int getType();
/**
* 获得个人请示,你要干什么?出去逛街?约会?还是看电影
*
* @return 干什么
*/
public String getRequest();
}
package com.iot.practice.designpattern.chainofresponsibility.chainofresponsibilitypattern;
import com.iot.practice.designpattern.chainofresponsibility.IWomen;
/**
* <p>IWomenImpl 此类用于:</p>
* <p>@author:hujm</p>
* <p>@date:2021年02月19日 11:23</p>
* <p>@remark:</p>
*/
public class IWomenImpl implements IWomen {
/**
* 通过一个int类型的参数来描述妇女的个人状况
* 1---未出嫁
* 2---出嫁
* 3---夫死
*/
private int type = 0;
/**
* 妇女的请示
*/
private String request = "";
/**
* 构造函数传递过来请求
*
* @param type 个人状况
* @param request 妇女的请示
*/
public IWomenImpl(int type, String request) {
this.type = type;
this.request = request;
// 为了显示好看点,我在这里做了点处理
switch(this.type) {
case 1:
this.request = "女儿的请求是:" + request;
break;
case 2:
this.request = "妻子的请求是:" + request;
break;
case 3:
this.request = "母亲的请求是:" + request;
break;
}
}
/**
* 获得自己的状况
*
* @return 自己的状况
*/
@Override
public int getType() {
return this.type;
}
/**
* 获得妇女的请求
*
* @return 妇女的请求
*/
@Override
public String getRequest() {
return this.request;
}
}
package com.iot.practice.designpattern.chainofresponsibility.chainofresponsibilitypattern;
import com.iot.practice.designpattern.chainofresponsibility.IWomen;
/**
* <p>Father 此类用于:</p>
* <p>@author:hujm</p>
* <p>@date:2021年02月19日 11:13</p>
* <p>@remark:</p>
*/
public class Father extends Handler {
/**
* 父亲只处理女儿的请求
*/
public Father() {
super(1);
}
/**
* 父亲的答复
*
* @param iWomen 女性统称
*/
@Override
public void response(IWomen iWomen) {
System.out.println("--------女儿向父亲请示-------");
System.out.println(iWomen.getRequest());
System.out.println("父亲的答复是:同意\n");
}
}
package com.iot.practice.designpattern.chainofresponsibility.chainofresponsibilitypattern;
import com.iot.practice.designpattern.chainofresponsibility.IWomen;
/**
* <p>Husband 此类用于:</p>
* <p>@author:hujm</p>
* <p>@date:2021年02月19日 11:15</p>
* <p>@remark:</p>
*/
public class Husband extends Handler {
/**
* 丈夫只处理妻子的请求
*/
public Husband() {
super(2);
}
/**
* 丈夫的答复
*
* @param iWomen 女性统称
*/
@Override
public void response(IWomen iWomen) {
System.out.println("--------妻子向丈夫请示-------");
System.out.println(iWomen.getRequest());
System.out.println("丈夫的答复是:同意\n");
}
}
package com.iot.practice.designpattern.chainofresponsibility.chainofresponsibilitypattern;
import com.iot.practice.designpattern.chainofresponsibility.IWomen;
/**
* <p>Son 此类用于:</p>
* <p>@author:hujm</p>
* <p>@date:2021年02月19日 11:18</p>
* <p>@remark:</p>
*/
public class Son extends Handler {
/**
* 儿子只处理母亲的请求
*/
public Son() {
super(3);
}
/**
* 儿子的答复
*
* @param iWomen 女性统称
*/
@Override
public void response(IWomen iWomen) {
System.out.println("--------母亲向儿子请示-------");
System.out.println(iWomen.getRequest());
System.out.println("儿子的答复是:同意\n");
}
}
完结!