什么是责任链模式?
职责链模式的定义:
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.(使多个对象都有机会处理请求,从而避免了请求的发送者和接受者之间的耦合关 系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理它为止。) |
责任链模式的重点是在“链”上,由一条链去处理相似的请求在链中决定谁来处理这个请求,并返回相应的结果,
通用类图如图16-1所示:
图16-1:命令模式模式通用类图
责任链模式的核心在“链”上,“链”是由多个处理者ConcreteHandler组成的,包含如下几个角色:
● Handler(抽象处理者):
抽象处理者实现三个职责:
- 一是定义一个请求的处理方法handleMessage,唯一对外开放的方法;
- 二是定义一个链的编排方法setNext,设置下一个处理者;
- 三是定义了具体的请求者必须实现的两个方法:定义自己能够处理的级别getHandlerLevel和具体的处理任务echo。
<span style="color:#141418"><span style="background-color:#ffffff"><code class="language-java"><span style="color:#a626a4">public</span> <span style="color:#a626a4">abstract</span> <span style="color:#a626a4">class</span> <span style="color:#4078f2">Handler</span> {
<span style="color:#a626a4">private</span> Handler nextHandler; <span style="color:#a0a1a7"><em>// 每个处理者都必须对请求做出处理</em></span>
<span style="color:#a626a4">public</span> <span style="color:#a626a4">final</span> Response <span style="color:#4078f2">handleMessage</span>(Request request) {
<span style="color:#986801">Response</span> <span style="color:#986801">response</span> <span style="color:#ab5656">=</span> <span style="color:#0184bb">null</span>;
<span style="color:#a0a1a7"><em>// 判断是否是自己的处理级别</em></span>
<span style="color:#a626a4">if</span> (<span style="color:#c18401">this</span>.getHandlerLevel().equals(request.getRequestLevel())) {
response = <span style="color:#c18401">this</span>.echo(request);
} <span style="color:#a626a4">else</span> { <span style="color:#a0a1a7"><em>// 不属于自己的处理级别</em></span>
<span style="color:#a0a1a7"><em>// 判断是否有下一个处理者</em></span>
<span style="color:#a626a4">if</span> (<span style="color:#c18401">this</span>.nextHandler != <span style="color:#0184bb">null</span>) {
response = <span style="color:#c18401">this</span>.nextHandler.handleMessage(request);
} <span style="color:#a626a4">else</span> {
<span style="color:#a0a1a7"><em>// 没有适当的处理者,业务自行处理</em></span>
}
}
<span style="color:#a626a4">return</span> response;
}
<span style="color:#a0a1a7"><em>// 设置下一个处理者是谁</em></span>
<span style="color:#a626a4">public</span> <span style="color:#a626a4">void</span> <span style="color:#4078f2">setNext</span>(Handler _handler) {
<span style="color:#c18401">this</span>.nextHandler = _handler;
}
<span style="color:#a0a1a7"><em>// 每个处理者都有一个处理级别</em></span>
<span style="color:#a626a4">protected</span> <span style="color:#a626a4">abstract</span> Level <span style="color:#4078f2">getHandlerLevel</span>();
<span style="color:#a0a1a7"><em>// 每个处理者都必须实现处理任务</em></span>
<span style="color:#a626a4">protected</span> <span style="color:#a626a4">abstract</span> Response <span style="color:#4078f2">echo</span>(Request request);
}
</code></span></span>
在处理者中涉及三个类:Level类负责定义请求和处理级别,Request类负责封装请 求,Response负责封装链中返回的结果,该三个类都需要根据业务产生,可以在实际应用中完成相关的业务填充:
<span style="color:#141418"><span style="background-color:#ffffff"><code class="language-java"><span style="color:#a626a4">public</span> <span style="color:#a626a4">class</span> <span style="color:#4078f2">Level</span> {
<span style="color:#a0a1a7"><em>//定义一个请求和处理等级</em></span>
}
<span style="color:#a626a4">public</span> <span style="color:#a626a4">class</span> <span style="color:#4078f2">Request</span> {
<span style="color:#a0a1a7"><em>//请求的等级 </em></span>
<span style="color:#a626a4">public</span> Level <span style="color:#4078f2">getRequestLevel</span>(){ <span style="color:#a626a4">return</span> <span style="color:#0184bb">null</span>; }
}
<span style="color:#a626a4">public</span> <span style="color:#a626a4">class</span> <span style="color:#4078f2">Response</span> {
<span style="color:#a0a1a7"><em>//处理者返回的数据</em></span>
}
</code></span></span>
● ConcreteHandler(具体处理者):
<span style="color:#141418"><span style="background-color:#ffffff"><code class="language-java"><span style="color:#a626a4">public</span> <span style="color:#a626a4">class</span> <span style="color:#4078f2">ConcreteHandler1</span> <span style="color:#a626a4">extends</span> <span style="color:#4078f2">Handler</span>{
<span style="color:#a0a1a7"><em>/**
* 设置自己的处理级别
*/</em></span>
<span style="color:#4078f2">@Override</span>
<span style="color:#a626a4">protected</span> Level <span style="color:#4078f2">getHandlerLevel</span>() {
<span style="color:#a0a1a7"><em>// TODO Auto-generated method stub</em></span>
<span style="color:#a626a4">return</span> <span style="color:#0184bb">null</span>;
}
<span style="color:#a0a1a7"><em>/**
* 定义自己的处理逻辑
*/</em></span>
<span style="color:#4078f2">@Override</span>
<span style="color:#a626a4">protected</span> Response <span style="color:#4078f2">echo</span>(Request request) {
<span style="color:#a0a1a7"><em>// TODO Auto-generated method stub</em></span>
<span style="color:#a626a4">return</span> <span style="color:#0184bb">null</span>;
}
}
</code></span></span>
定义了三个处理者,代码都是一样,此处不重复贴出。
● Client(客户端):在客户端或高层模块中对链进行组装,并传递请求,返回结果。
<span style="color:#141418"><span style="background-color:#ffffff"><code class="language-java"><span style="color:#a626a4">public</span> <span style="color:#a626a4">class</span> <span style="color:#4078f2">Client</span> {
<span style="color:#a0a1a7"><em>/**
* <span style="color:#a626a4">@param</span> args
*/</em></span>
<span style="color:#a626a4">public</span> <span style="color:#a626a4">static</span> <span style="color:#a626a4">void</span> <span style="color:#4078f2">main</span>(String[] args) {
<span style="color:#a0a1a7"><em>//声明所有的处理节点</em></span>
<span style="color:#986801">Handler</span> <span style="color:#986801">handler1</span> <span style="color:#ab5656">=</span> <span style="color:#a626a4">new</span> <span style="color:#4078f2">ConcreteHandler1</span>();
<span style="color:#986801">Handler</span> <span style="color:#986801">handler2</span> <span style="color:#ab5656">=</span> <span style="color:#a626a4">new</span> <span style="color:#4078f2">ConcreteHandler2</span>();
<span style="color:#986801">Handler</span> <span style="color:#986801">handler3</span> <span style="color:#ab5656">=</span> <span style="color:#a626a4">new</span> <span style="color:#4078f2">ConcreteHandler3</span>();
<span style="color:#a0a1a7"><em>//设置链中的阶段顺序1-->2-->3 </em></span>
handler1.setNext(handler2);
handler2.setNext(handler3);
<span style="color:#a0a1a7"><em>//提交请求,返回结果 </em></span>
<span style="color:#986801">Response</span> <span style="color:#986801">response</span> <span style="color:#ab5656">=</span> handler1.handleMessage(<span style="color:#a626a4">new</span> <span style="color:#4078f2">Request</span>());
}
}
</code></span></span>
在实际应用中,一般会有一个封装类对责任模式进行封装,也就是替代Client类,直接返回链中的第一个处理者,具体链的设置不需要高层次模块关系,这样,更简化了高层次模 块的调用,减少模块间的耦合,提高系统的灵活性。
为什么要用责任链模式
这里有一个业务场景,在万恶的封建社会,女子讲究“三从四德”,“三从”是指“未嫁从父、既嫁从夫、夫死从子”。
不使用责任链模式
以批判的态度去分析这个业务场景,类图如下:
图16-2:腐朽的“三从”类图
IHandler是三个有决策权对象的接口,IWomen是女性的代码。下面是实现:
- IWomen(妇女接口):
<span style="color:#141418"><span style="background-color:#ffffff"><code class="language-java"><span style="color:#a626a4">public</span> <span style="color:#a626a4">interface</span> <span style="color:#4078f2">IWomen</span> {
<span style="color:#a0a1a7"><em>//获得个人状况 </em></span>
<span style="color:#a626a4">public</span> <span style="color:#986801">int</span> <span style="color:#4078f2">getType</span>();
<span style="color:#a0a1a7"><em>//获得个人请示 </em></span>
<span style="color:#a626a4">public</span> String <span style="color:#4078f2">getRequest</span>();
}
</code></span></span>
- Women(妇女实现类):
<span style="color:#141418"><span style="background-color:#ffffff"><code class="language-java"><span style="color:#a626a4">public</span> <span style="color:#a626a4">class</span> <span style="color:#4078f2">Women</span> <span style="color:#a626a4">implements</span> <span style="color:#4078f2">IWomen</span>{
<span style="color:#a0a1a7"><em>/** 通过一个int类型的参数来描述妇女的个人状况 * 1--未出嫁 * 2--出嫁 * 3--夫死 */</em></span>
<span style="color:#a626a4">private</span> <span style="color:#986801">int</span> <span style="color:#986801">type</span> <span style="color:#ab5656">=</span> <span style="color:#986801">0</span>;
<span style="color:#a0a1a7"><em>// 妇女的请示</em></span>
<span style="color:#a626a4">private</span> <span style="color:#986801">String</span> <span style="color:#986801">request</span> <span style="color:#ab5656">=</span> <span style="color:#50a14f">""</span>;
<span style="color:#a0a1a7"><em>// 构造函数传递过来请求</em></span>
<span style="color:#a626a4">public</span> <span style="color:#4078f2">Women</span>(<span style="color:#986801">int</span> _type, String _request) {
<span style="color:#c18401">this</span>.type = _type;
<span style="color:#c18401">this</span>.request = _request;
}
<span style="color:#a0a1a7"><em>// 获得自己的状况</em></span>
<span style="color:#a626a4">public</span> <span style="color:#986801">int</span> <span style="color:#4078f2">getType</span>() {
<span style="color:#a626a4">return</span> <span style="color:#c18401">this</span>.type;
}
<span style="color:#a0a1a7"><em>// 获得妇女的请求</em></span>
<span style="color:#a626a4">public</span> String <span style="color:#4078f2">getRequest</span>() {
<span style="color:#a626a4">return</span> <span style="color:#c18401">this</span>.request;
}
}
</code></span></span>
- IHandler(有处理权的人员接口):
<span style="color:#141418"><span style="background-color:#ffffff"><code class="language-java"><span style="color:#a626a4">public</span> <span style="color:#a626a4">interface</span> <span style="color:#4078f2">IHandler</span> {
<span style="color:#a0a1a7"><em>//一个女性(女儿、妻子或者母亲)要求逛街,你要处理这个请求 </em></span>
<span style="color:#a626a4">public</span> <span style="color:#a626a4">void</span> <span style="color:#4078f2">HandleMessage</span>(IWomen women);
}
</code></span></span>
- 实现类:有处理权的人对妇女的请求进行处理,分别有三个实现类,在女儿没有出嫁之前父亲是有决定权的;在女性出嫁后,丈夫有决定权;在女性丧偶后,对母亲提出的请求儿子有决定权;
<span style="color:#141418"><span style="background-color:#ffffff"><code class="language-java"><span style="color:#a626a4">public</span> <span style="color:#a626a4">class</span> <span style="color:#4078f2">Father</span> <span style="color:#a626a4">implements</span> <span style="color:#4078f2">IHandler</span> {
<span style="color:#a0a1a7"><em>// 未出嫁的女儿来请示父亲</em></span>
<span style="color:#a626a4">public</span> <span style="color:#a626a4">void</span> <span style="color:#4078f2">HandleMessage</span>(IWomen women) {
System.out.println(<span style="color:#50a14f">"女儿的请示是:"</span> + women.getRequest());
System.out.println(<span style="color:#50a14f">"父亲的答复是:同意"</span>);
}
}
<span style="color:#a626a4">public</span> <span style="color:#a626a4">class</span> <span style="color:#4078f2">Husband</span> <span style="color:#a626a4">implements</span> <span style="color:#4078f2">IHandler</span> {
<span style="color:#a0a1a7"><em>// 妻子向丈夫请示</em></span>
<span style="color:#a626a4">public</span> <span style="color:#a626a4">void</span> <span style="color:#4078f2">HandleMessage</span>(IWomen women) {
System.out.println(<span style="color:#50a14f">"妻子的请示是:"</span> + women.getRequest());
System.out.println(<span style="color:#50a14f">"丈夫的答复是:同意"</span>);
}
}
<span style="color:#a626a4">public</span> <span style="color:#a626a4">class</span> <span style="color:#4078f2">Son</span> <span style="color:#a626a4">implements</span> <span style="color:#4078f2">IHandler</span> {
<span style="color:#a0a1a7"><em>// 母亲向儿子请示</em></span>
<span style="color:#a626a4">public</span> <span style="color:#a626a4">void</span> <span style="color:#4078f2">HandleMessage</span>(IWomen women) {
System.out.println(<span style="color:#50a14f">"母亲的请示是:"</span> + women.getRequest());
System.out.println(<span style="color:#50a14f">"儿子的答复是:同意"</span>);
}
}
</code></span></span>
- 场景类:
<span style="color:#141418"><span style="background-color:#ffffff"><code class="language-java"><span style="color:#a626a4">public</span> <span style="color:#a626a4">class</span> <span style="color:#4078f2">Client</span> {
<span style="color:#a626a4">public</span> <span style="color:#a626a4">static</span> <span style="color:#a626a4">void</span> <span style="color:#4078f2">main</span>(String[] args) {
<span style="color:#a0a1a7"><em>// 随机挑选几个女性</em></span>
<span style="color:#986801">Random</span> <span style="color:#986801">rand</span> <span style="color:#ab5656">=</span> <span style="color:#a626a4">new</span> <span style="color:#4078f2">Random</span>();
ArrayList<IWomen> arrayList = <span style="color:#a626a4">new</span> <span style="color:#4078f2">ArrayList</span>();
<span style="color:#a626a4">for</span> (<span style="color:#986801">int</span> <span style="color:#986801">i</span> <span style="color:#ab5656">=</span> <span style="color:#986801">0</span>; i < <span style="color:#986801">5</span>; i++) {
arrayList.add(<span style="color:#a626a4">new</span> <span style="color:#4078f2">Women</span>(rand.nextInt(<span style="color:#986801">4</span>), <span style="color:#50a14f">"看戏"</span>));
}
<span style="color:#a0a1a7"><em>// 定义三个请示对象</em></span>
<span style="color:#986801">IHandler</span> <span style="color:#986801">father</span> <span style="color:#ab5656">=</span> <span style="color:#a626a4">new</span> <span style="color:#4078f2">Father</span>();
<span style="color:#986801">IHandler</span> <span style="color:#986801">husband</span> <span style="color:#ab5656">=</span> <span style="color:#a626a4">new</span> <span style="color:#4078f2">Husband</span>();
<span style="color:#986801">IHandler</span> <span style="color:#986801">son</span> <span style="color:#ab5656">=</span> <span style="color:#a626a4">new</span> <span style="color:#4078f2">Son</span>();
<span style="color:#a626a4">for</span> (IWomen women : arrayList) {
<span style="color:#a626a4">if</span> (women.getType() == <span style="color:#986801">1</span>) {
<span style="color:#a0a1a7"><em>// 未结婚少女,请示父亲</em></span>
System.out.println(<span style="color:#50a14f">"\n--------女儿向父亲请示-------"</span>);
father.HandleMessage(women);
} <span style="color:#a626a4">else</span> <span style="color:#a626a4">if</span> (women.getType() == <span style="color:#986801">2</span>) {
<span style="color:#a0a1a7"><em>// 已婚少妇,请示丈夫</em></span>
System.out.println(<span style="color:#50a14f">"\n--------妻子向丈夫请示-------"</span>);
husband.HandleMessage(women);
} <span style="color:#a626a4">else</span> <span style="color:#a626a4">if</span> (women.getType() == <span style="color:#986801">3</span>) {
<span style="color:#a0a1a7"><em>// 母亲请示儿子</em></span>
System.out.println(<span style="color:#50a14f">"\n--------母亲向儿子请示-------"</span>);
son.HandleMessage(women);
} <span style="color:#a626a4">else</span> {
<span style="color:#a0a1a7"><em>// 暂时什么也不做</em></span>
}
}
}
}
</code></span></span>
首先是通过随机方法产生了5个古代妇女的对象,然后看她们是如何就看戏这件事去请示的,运行结果如下:
OK,业务已经实现了,但是明显这个业务实现是存在问题的。
● 职责界定不清晰
对女儿提出的请示,应该在父亲类中做出决定,父亲有责任、有义务处理女儿的请示, 因此Father类应该是知道女儿的请求自己处理,而不是在Client类中进行组装出来,也就是说原本应该是父亲这个类做的事情抛给了其他类进行处理。
● 代码臃肿
我们在Client类中写了if...else的判断条件,而且能随着能处理该类型的请示人员越多,if...else的判断就越多。
● 耦合过重
这是什么意思呢,我们要根据Women的type来决定使用IHandler的那个实现类来处理请 求。有一个问题是:如果IHandler的实现类继续扩展怎么办?如果修改Client类,那就违背了开闭原则。
● 异常情况欠考虑
妻子只能向丈夫请示吗?如果妻子(比如一个现代女性穿越到古代了,不懂什么“三从四德”)向自己的父亲请示了,父亲应该做何处理?我们的程序上可没有体现出来,逻辑失败了!
引入责任链模式
针对上面的问题,这时候就该考虑引入责任链模式了。
可以抽象成这样一个结构,女性的请求先发送到父亲类,父亲类一看是自己要处理的,就 作出回应处理,如果女儿已经出嫁了,那就要把这个请求转发到女婿来处理,那女婿一旦去天国报道了,那就由儿子来处理这个请求,类似于如图16-3所示的顺序处理图:
图16-3:女性请示的顺序处理图
父亲、丈夫、儿子每个节点有两个选择:要么承担责任,做出回应;要么把请求转发到后序环节。
根据责任链模式,修改后的类图如下:
图16-4:使用责任链模式后的女子“三从”类图
实现如下:
- 改造后的Handler类:
<span style="color:#141418"><span style="background-color:#ffffff"><code class="language-java"><span style="color:#a626a4">public</span> <span style="color:#a626a4">abstract</span> <span style="color:#a626a4">class</span> <span style="color:#4078f2">Handler</span> {
<span style="color:#a626a4">public</span> <span style="color:#a626a4">final</span> <span style="color:#a626a4">static</span> <span style="color:#986801">int</span> <span style="color:#986801">FATHER_LEVEL_REQUEST</span> <span style="color:#ab5656">=</span> <span style="color:#986801">1</span>;
<span style="color:#a626a4">public</span> <span style="color:#a626a4">final</span> <span style="color:#a626a4">static</span> <span style="color:#986801">int</span> <span style="color:#986801">HUSBAND_LEVEL_REQUEST</span> <span style="color:#ab5656">=</span> <span style="color:#986801">2</span>;
<span style="color:#a626a4">public</span> <span style="color:#a626a4">final</span> <span style="color:#a626a4">static</span> <span style="color:#986801">int</span> <span style="color:#986801">SON_LEVEL_REQUEST</span> <span style="color:#ab5656">=</span> <span style="color:#986801">3</span>;
<span style="color:#a0a1a7"><em>// 能处理的级别</em></span>
<span style="color:#a626a4">private</span> <span style="color:#986801">int</span> <span style="color:#986801">level</span> <span style="color:#ab5656">=</span> <span style="color:#986801">0</span>;
<span style="color:#a0a1a7"><em>// 责任传递,下一个人责任人是谁</em></span>
<span style="color:#a626a4">private</span> Handler nextHandler;
<span style="color:#a0a1a7"><em>// 每个类都要说明一下自己能处理哪些请求</em></span>
<span style="color:#a626a4">public</span> <span style="color:#4078f2">Handler</span>(<span style="color:#986801">int</span> _level) {
<span style="color:#c18401">this</span>.level = _level;
}
<span style="color:#a0a1a7"><em>// 一个女性(女儿、妻子或者是母亲)要求逛街,你要处理这个请求</em></span>
<span style="color:#a626a4">public</span> <span style="color:#a626a4">final</span> <span style="color:#a626a4">void</span> <span style="color:#4078f2">HandleMessage</span>(IWomen women) {
<span style="color:#a626a4">if</span> (women.getType() == <span style="color:#c18401">this</span>.level) {
<span style="color:#c18401">this</span>.response(women);
} <span style="color:#a626a4">else</span> <span style="color:#a626a4">if</span> (<span style="color:#c18401">this</span>.nextHandler != <span style="color:#0184bb">null</span>) {
<span style="color:#a0a1a7"><em>// 有后续环节,才把请求往后递送</em></span>
<span style="color:#c18401">this</span>.nextHandler.HandleMessage(women);
} <span style="color:#a626a4">else</span> {
<span style="color:#a0a1a7"><em>// 已经没有后续处理人了,不用处理了</em></span>
System.out.println(<span style="color:#50a14f">"---没地方请示了,按不同意处理---\n"</span>);
}
}
<span style="color:#a0a1a7"><em>/** 如果不属于你处理的请求,你应该让她找下一个环节的人,如女儿出嫁了, * 还向父亲请示是否可以逛街,那父亲就应该告诉女儿,应该找丈夫请示 */</em></span>
<span style="color:#a626a4">public</span> <span style="color:#a626a4">void</span> <span style="color:#4078f2">setNext</span>(Handler _handler) {
<span style="color:#c18401">this</span>.nextHandler = _handler;
}
<span style="color:#a0a1a7"><em>//有请示那当然要回应</em></span>
<span style="color:#a626a4">protected</span> <span style="color:#a626a4">abstract</span> <span style="color:#a626a4">void</span> <span style="color:#4078f2">response</span>(IWomen women);
}
</code></span></span>
在这里也用到模板方法模式,在模板方法中判断请求的级别和当前能够处理的级别,如果相同则调用基本方法,做出 反馈;如果不相等,则传递到下一个环节,由下一环节做出回应,如果已经达到环节结尾, 则直接做不同意处理。基本方法response需要各个实现类实现,每个实现类只要实现两个职 责:一是定义自己能够处理的等级级别;二是对请求做出回应。
三个实现类如下:三个实现类分别处理不同等级的请求
- 父亲类:
<span style="color:#141418"><span style="background-color:#ffffff"><code class="language-java"><span style="color:#a626a4">public</span> <span style="color:#a626a4">class</span> <span style="color:#4078f2">Father</span> <span style="color:#a626a4">extends</span> <span style="color:#4078f2">Handler</span> {
<span style="color:#a0a1a7"><em>// 父亲只处理女儿的请求</em></span>
<span style="color:#a626a4">public</span> <span style="color:#4078f2">Father</span>() {
<span style="color:#c18401">super</span>(Handler.FATHER_LEVEL_REQUEST);
}
<span style="color:#a0a1a7"><em>// 父亲的答复</em></span>
<span style="color:#a626a4">protected</span> <span style="color:#a626a4">void</span> <span style="color:#4078f2">response</span>(IWomen women) {
System.out.println(<span style="color:#50a14f">"--------女儿向父亲请示-------"</span>);
System.out.println(women.getRequest());
System.out.println(<span style="color:#50a14f">"父亲的答复是:同意\n"</span>);
}
}
</code></span></span>
- 丈夫类:
<span style="color:#141418"><span style="background-color:#ffffff"><code class="language-java"><span style="color:#a626a4">public</span> <span style="color:#a626a4">class</span> <span style="color:#4078f2">Husband</span> <span style="color:#a626a4">extends</span> <span style="color:#4078f2">Handler</span> {
<span style="color:#a0a1a7"><em>// 丈夫只处理妻子的请求</em></span>
<span style="color:#a626a4">public</span> <span style="color:#4078f2">Husband</span>() {
<span style="color:#c18401">super</span>(Handler.HUSBAND_LEVEL_REQUEST);
}
<span style="color:#a0a1a7"><em>//丈夫请示的答复 </em></span>
<span style="color:#a626a4">protected</span> <span style="color:#a626a4">void</span> <span style="color:#4078f2">response</span>(IWomen women) {
System.out.println(<span style="color:#50a14f">"--------妻子向丈夫请示-------"</span>);
System.out.println(women.getRequest());
System.out.println(<span style="color:#50a14f">"丈夫的答复是:同意\n"</span>);
}
}
</code></span></span>
- 儿子类:
<span style="color:#141418"><span style="background-color:#ffffff"><code class="language-java"><span style="color:#a626a4">public</span> <span style="color:#a626a4">class</span> <span style="color:#4078f2">Son</span> <span style="color:#a626a4">extends</span> <span style="color:#4078f2">Handler</span> {
<span style="color:#a0a1a7"><em>// 儿子只处理母亲的请求</em></span>
<span style="color:#a626a4">public</span> <span style="color:#4078f2">Son</span>() {
<span style="color:#c18401">super</span>(Handler.SON_LEVEL_REQUEST);
}
<span style="color:#a0a1a7"><em>// 儿子的答复</em></span>
<span style="color:#a626a4">protected</span> <span style="color:#a626a4">void</span> <span style="color:#4078f2">response</span>(IWomen women) {
System.out.println(<span style="color:#50a14f">"--------母亲向儿子请示-------"</span>);
System.out.println(women.getRequest());
System.out.println(<span style="color:#50a14f">"儿子的答复是:同意\n"</span>);
}
}
</code></span></span>
-
Women类的接口没有任何变化
-
实现类稍微有些变化:为了展示结果清晰一点,输出请求的来源
<span style="color:#141418"><span style="background-color:#ffffff"><code class="language-java"><span style="color:#a626a4">public</span> <span style="color:#a626a4">class</span> <span style="color:#4078f2">Women</span> <span style="color:#a626a4">implements</span> <span style="color:#4078f2">IWomen</span> {
<span style="color:#a0a1a7"><em>/**
* 通过一个int类型的参数来描述妇女的个人状况 1--未出嫁 * 2--出嫁 * 3--夫死
*/</em></span>
<span style="color:#a626a4">private</span> <span style="color:#986801">int</span> <span style="color:#986801">type</span> <span style="color:#ab5656">=</span> <span style="color:#986801">0</span>;
<span style="color:#a0a1a7"><em>// 妇女的请示</em></span>
<span style="color:#a626a4">private</span> <span style="color:#986801">String</span> <span style="color:#986801">request</span> <span style="color:#ab5656">=</span> <span style="color:#50a14f">""</span>;
<span style="color:#a0a1a7"><em>// 构造函数传递过来请求</em></span>
<span style="color:#a626a4">public</span> <span style="color:#4078f2">Women</span>(<span style="color:#986801">int</span> _type, String _request) {
<span style="color:#c18401">this</span>.type = _type; <span style="color:#a0a1a7"><em>// 为了便于显示,在这里做了点处理</em></span>
<span style="color:#a626a4">switch</span> (<span style="color:#c18401">this</span>.type) {
<span style="color:#a626a4">case</span> <span style="color:#986801">1</span>:
<span style="color:#c18401">this</span>.request = <span style="color:#50a14f">"女儿的请求是:"</span> + _request;
<span style="color:#a626a4">break</span>;
<span style="color:#a626a4">case</span> <span style="color:#986801">2</span>:
<span style="color:#c18401">this</span>.request = <span style="color:#50a14f">"妻子的请求是:"</span> + _request;
<span style="color:#a626a4">break</span>;
<span style="color:#a626a4">case</span> <span style="color:#986801">3</span>:
<span style="color:#c18401">this</span>.request = <span style="color:#50a14f">"母亲的请求是:"</span> + _request;
}
}
<span style="color:#a0a1a7"><em>// 获得自己的状况</em></span>
<span style="color:#a626a4">public</span> <span style="color:#986801">int</span> <span style="color:#4078f2">getType</span>() {
<span style="color:#a626a4">return</span> <span style="color:#c18401">this</span>.type;
}
<span style="color:#a0a1a7"><em>// 获得妇女的请求</em></span>
<span style="color:#a626a4">public</span> String <span style="color:#4078f2">getRequest</span>() {
<span style="color:#a626a4">return</span> <span style="color:#c18401">this</span>.request;
}
}
</code></span></span>
- 场景类:
<span style="color:#141418"><span style="background-color:#ffffff"><code class="language-java"><span style="color:#a626a4">public</span> <span style="color:#a626a4">class</span> <span style="color:#4078f2">Client</span> {
<span style="color:#a626a4">public</span> <span style="color:#a626a4">static</span> <span style="color:#a626a4">void</span> <span style="color:#4078f2">main</span>(String[] args) {
<span style="color:#a0a1a7"><em>// 随机挑选几个女性</em></span>
<span style="color:#986801">Random</span> <span style="color:#986801">rand</span> <span style="color:#ab5656">=</span> <span style="color:#a626a4">new</span> <span style="color:#4078f2">Random</span>();
ArrayList<IWomen> arrayList = <span style="color:#a626a4">new</span> <span style="color:#4078f2">ArrayList</span>();
<span style="color:#a626a4">for</span> (<span style="color:#986801">int</span> <span style="color:#986801">i</span> <span style="color:#ab5656">=</span> <span style="color:#986801">0</span>; i < <span style="color:#986801">5</span>; i++) {
arrayList.add(<span style="color:#a626a4">new</span> <span style="color:#4078f2">Women</span>(rand.nextInt(<span style="color:#986801">4</span>), <span style="color:#50a14f">"我要看戏"</span>));
}
<span style="color:#a0a1a7"><em>// 定义三个请示对象</em></span>
<span style="color:#986801">Handler</span> <span style="color:#986801">father</span> <span style="color:#ab5656">=</span> <span style="color:#a626a4">new</span> <span style="color:#4078f2">Father</span>();
<span style="color:#986801">Handler</span> <span style="color:#986801">husband</span> <span style="color:#ab5656">=</span> <span style="color:#a626a4">new</span> <span style="color:#4078f2">Husband</span>();
<span style="color:#986801">Handler</span> <span style="color:#986801">son</span> <span style="color:#ab5656">=</span> <span style="color:#a626a4">new</span> <span style="color:#4078f2">Son</span>();
<span style="color:#a0a1a7"><em>// 设置请示顺序</em></span>
father.setNext(husband);
husband.setNext(son);
<span style="color:#a626a4">for</span> (IWomen women : arrayList) {
father.HandleMessage(women);
}
}
}
</code></span></span>
在Client中设置请求的传递顺序,先向父亲请示,不是父亲应该解决的问题,则由父亲 传递到丈夫类解决,若不是丈夫类解决的问题则传递到儿子类解决,最终的结果必然有一个 返回,其运行结果如下所示:
业务调用类Client不用再去做判断到底是需要谁去处理,而且Handler抽象类的子类可以继续增加下去,只需要扩展传递链而已,调用类可以不用了解变化过程,甚至是谁在处理这个请求都不用知道。
责任链模式优缺点
责任链模式优点
- 责任链模式使得一个对象无须知道是其他哪一个对象处理其请求,对象仅需知道该请求会 被处理即可,接收者和发送者都没有对方的明确信息,且链中的对象不需要知道链的结构, 由客户端负责链的创建,降低了系统的耦合度。
- 请求处理对象仅需维持一个指向其后继者的引用,而不需要维持它对所有的候选处理者的 引用,可简化对象的相互连接。
- 在给对象分派职责时,职责链可以给我们更多的灵活性,可以通过在运行时对该链进行动 态的增加或修改来增加或改变处理一个请求的职责。
- 在系统中增加一个新的具体请求处理者时无须修改原有系统的代码,只需要在客户端重新 建链即可,从这一点来看是符合“开闭原则”的。
责任链模式缺点
- 由于一个请求没有明确的接收者,那么就不能保证它一定会被处理,该请求可能一直到链 的末端都得不到处理;一个请求也可能因职责链没有被正确配置而得不到处理。
- 对于比较长的职责链,请求的处理可能涉及到多个处理对象,系统性能将受到一定影响, 而且在进行代码调试时不太方便。
- 如果建链不当,可能会造成循环调用,将导致系统陷入死循环。
责任链模式应用场景
在以下情况下可以考虑使用职责链模式:
- 有多个对象可以处理同一个请求,具体哪个对象处理该请求待运行时刻再确定,客户端只 需将请求提交到链上,而无须关心请求的处理对象是谁以及它是如何处理的。
- 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
- 可动态指定一组对象处理请求,客户端可以动态创建职责链来处理请求,还可以改变链中 处理者之间的先后次序。