职责链模式(Chain of Responsibility):很多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
一、职责链模式
职责链的UML图:
职责链由以下部分组成:
抽象处理者角色(Handler):定义一个处理请求的接口,和一个后继连接(可选)
具体处理者角色(ConcreteHandler):处理它所负责的请求,可以访问后继者,如果可以处理请求则处理,否则将该请求转给他的后继者。
代码部分:
Handler:
abstract class Handler{
private Handler successor;
public void setSuccessor(Handler successor) {
this.successor = successor;
}
public abstract void handleRequest();
public Handler getSuccessor(){
return successor;
}
}
ConcreteHandler:
class ConcreteHandler extends Handler{
public void handleRequest() {
if(getSuccessor() != null){
System.out.println("放过请求");
getSuccessor().handleRequest();
}else{
System.out.println("处理请求");
}
}
}
客户端调用:
public static void main(String[] args) {
Handler handler1 = new ConcreteHandler();
Handler handler2 = new ConcreteHandler();
handler1.setSuccessor(handler2);
handler1.handleRequest();
}
运行结果:
二、案例分析
在《西游记》中,唐僧被妖怪捉走后,悟空总是要到天庭寻找帮手,请来的神仙若打不过妖怪,就得重新再找帮手了。
在第五十二回《 悟空大闹金山兜洞 如来暗示主人公》中,为了降服金皘山大王兕大王,先派李天王父子,战败;再派火德星君,战败;再派水德星君,战败;无奈,找到佛祖(佛祖怎会亲自上场),再找太上老君,最终降服妖怪,度过一难。这里面就隐藏着职责链模式。
孙悟空,就是客户端的请求者。神仙打怪是抽象处理者角色, 每一个神仙都是具体的处理者角色, 用代码实现这个情景:
抽象神仙类:
abstract class Immortal{
private Immortal immortal;
public void setImmortal(Immortal immortal) {
this.immortal = immortal;
}
public abstract void handleRequest();
public Immortal getSuccessor(){
return immortal;
}
}
各类神仙:
class NeZha extends Immortal{
public void handleRequest() {
if(getSuccessor() != null){
System.out.println("我是哪吒,我打不过妖怪了,找人吧");
getSuccessor().handleRequest();
}else{
System.out.println("处理请求");
}
}
}
class WaterMan extends Immortal{
public void handleRequest() {
if(getSuccessor() != null){
System.out.println("水德星君,我打不过妖怪,找人吧");
getSuccessor().handleRequest();
}else{
System.out.println("处理请求");
}
}
}
class FireMan extends Immortal{
public void handleRequest() {
if(getSuccessor() != null){
System.out.println("火德星君,我打不过妖怪,找人吧");
getSuccessor().handleRequest();
}else{
System.out.println("处理请求");
}
}
}
class Buddha extends Immortal{
public void handleRequest() {
if(getSuccessor() != null){
System.out.println("我是佛祖,你去找太上老君");
getSuccessor().handleRequest();
}else{
System.out.println("处理请求");
}
}
}
class OldMan extends Immortal{
public void handleRequest() {
if(getSuccessor() != null){
System.out.println("我是太上老君,我打不过妖怪");
getSuccessor().handleRequest();
}else{
System.out.println("这是我的青牛,我来收了他!");
}
}
}
故事上演:
public static void main(String[] args) {
Immortal immortal1 = new NeZha();
Immortal immortal2 = new WaterMan();
Immortal immortal3 = new FireMan();
Immortal immortal4 = new Buddha();
Immortal immortal5 = new OldMan();
immortal1.setImmortal(immortal2);
immortal2.setImmortal(immortal3);
immortal3.setImmortal(immortal4);
immortal4.setImmortal(immortal5);
immortal1.handleRequest();
}
运行结果:
模式总结
职责链模式说明:
客户端发送一个请求,有多个对象都有机会来处理这个请求,但客户端不知道究竟谁来处理。
客户端只知道他提交请求的第一个对象,从第一个对象开始处理,整个职责链中的对象要么处理请求,要么转发给下一个接受者。
在标准的职责链模式中,当对象处理了请求,这个请求就会到此为止,不再被传递和处理。
在职责链模式中,请求不一定会被处理,因为可能没有合适的处理者。请求在职责链中从头到尾,每个处理对象都判断不属于自己处理,最后请求就没有对象来处理。
职责链模式的优点:
降低耦合度 :该模式使得一个对象无需知道是其他哪一个对象处理其请求。对象仅需知道该请求会被“正确”地处理。接收者和发送者都没有对方的明确的信息,且链中的对象不需知道链的结构。
职责链可简化对象的相互连接 : 结果是,职责链可简化对象的相互连接。它们仅需保持一个指向其后继者的引用,而不需保持它所有的候选接受者的引用。
增强了给对象指派职责的灵活性 :当在对象中分派职责时,职责链给你更多的灵活性。你可以通过在运行时刻对该链进行动态的增加或修改来增加或改变处理一个请求的那些职责。你可以将这种机制与静态的特例化处理对象的继承机制结合起来使用。
增加新的请求处理类很方便。
欢迎大家评论留言,点击查看更多设计模式。