目录
- 应用场景
- 简单示例
- 责任链模式
- 定义
- 意图
- 主要解决问题
- 何时使用
- 优缺点
- 击鼓传花的故事
http web请求处理,请求过来后将经过转码、解析、参数封装、鉴权等一系列的处理(责任),而且要经过多少处理是可以灵活调整的
那么该怎么做呢?
将所有的处理都写在一个类中行不行呢?
分成多个类又该如何灵活的组合在一起呢?
简单示例
Request类:
public interface Request { //do something... }
ResponsibilityChain类:
public class ResponsibilityChain { private List<Responsibility> responsibilityList = new ArrayList<>(); private Integer index = 0; public void process(Request request) { if (this.index < responsibilityList.size()) { this.responsibilityList.get(index++).process(request, this); } } /** 加入链中 */ public void register(Responsibility responsibility) { this.responsibilityList.add(responsibility); } }
Responsibility接口:
public interface Responsibility { void process(Request request, ResponsibilityChain chain); }
Responsibility实现类:
public class ResponsibilityA implements Responsibility { @Override public void process(Request request, ResponsibilityChain chain) { System.out.println("转码"); chain.process(request); } }
public class ResponsibilityB implements Responsibility { @Override public void process(Request request, ResponsibilityChain chain) { System.out.println("解析"); chain.process(request); } }
public class ResponsibilityC implements Responsibility { @Override public void process(Request request, ResponsibilityChain chain) { System.out.println("参数封装"); chain.process(request); } }
public class ResponsibilityD implements Responsibility { @Override public void process(Request request, ResponsibilityChain chain) { System.out.println("鉴权"); chain.process(request); } }
测试类:
public class Test { public static void main(String[] args) { ResponsibilityChain chain = new ResponsibilityChain(); chain.register(new ResponsibilityA()); chain.register(new ResponsibilityB()); chain.register(new ResponsibilityC()); chain.register(new ResponsibilityD()); chain.process(new Request() { }); } }
类图:
定义
所有的处理者,都加入到这个链式,一个处理完后,转给下一个
或者说每个接收者都包含对另一个接收者的引用,如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者
- 抽象出责任接口,具体责任逻辑实现接口
- 根据处理过程需要,将具体实现组合成链
- 使用者使用链
典型的代表:Filter、Interceptor
意图
避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止
主要解决问题
职责链上的处理者负责处理请求,客户端只需要将请求发送到职责链上就行了,不需要关系处理的细节和请求的传递,请求的发送者和处理者解耦了
何时使用
- 系统已经有一个由处理者对象组成的链,这个链可能有合成模式给出
- 有多于一个的处理者对象会处理一个请求,而且事先并不清楚到底由哪一个处理者对象处理一个请求,处理者对象是动态确定的
- 系统想发出一个请求给多个处理者对象中的某一个,但是不明显指定哪一个处理者对象会处理该请求
- 处理一个请求的处理者对象集合需要动态的指定时
优缺点
优点:
- 发送者和接收者解耦,低耦合
- 简化了对象。使得对象不需要知道链的结构
- 通过改变链内的成员或者调动它们的次序,允许动态地新增或者删除责任
- 增加新的请求处理类很方便
缺点:
- 不能保证请求一定被接收
- 系统性能将受到一定影响,而且在进行代码调试时不太方便,可能会造成循环调用
- 可能不容易观察运行时的特征,有碍于除错
类图如下:
涉及到的角色:
- 抽象处理者(Handler)角色:定义一个处理请求的接口,如果需要,接口可以定义出一个方法,以设定和返回对下家的引用,这个角色通常由一个抽象类或者接口实现
- 具体处理者(ConcreteHandler)角色:具体处理者接收到请求后,可以选择将请求处理掉,或者传给下一个;具体处理者持有对下一个的引用,因此如果需要,具体处理者可以访问下一个
代码示例:
Handler类:
public abstract class Handler { protected Handler successor; /** 调用此方法处理请求 */ public abstract void handlerRequest(); /** 取值方法 */ public Handler getSuccessor() { return successor; } /** 调用此方法设置下一个 */ public void setSuccessor(Handler successor) { this.successor = successor; } }
ConcreteHandler类:
public class ConcreteHandler1 extends Handler { @Override public void handlerRequest() { if (getSuccessor() != null) { System.out.println("请求传递到下一个:" + getSuccessor().getClass().getName()); getSuccessor().handlerRequest(); } else { System.out.println("请求在ConcreteHandler1被处理了"); } } }
public class ConcreteHandler2 extends Handler { @Override public void handlerRequest() { if (getSuccessor() != null) { System.out.println("请求传递到下一个:" + getSuccessor()); getSuccessor().handlerRequest(); } else { System.out.println("请求在ConcreteHandler2被处理了"); } } }
客户端:
public class Client { static private Handler handler1; static private Handler handler2; public static void main(String[] args) { handler1 = new ConcreteHandler1(); handler2 = new ConcreteHandler2(); handler1.setSuccessor(handler2); handler1.handlerRequest(); } }
类图:
击鼓传花是一种热闹而又紧张的饮酒游戏,在酒宴上宾客依次坐定,由一人击鼓,开始击鼓时,花束就开始依次传递,鼓声一落,如果花束在谁手里,谁就开始饮酒了;下面以《红楼梦》中击鼓传花的故事,写一个小例子:
抽象接口Player类:
public abstract class Player { private Player player; /** 需要执行酒令的请求 */ abstract public void handlerRequest(int index); /** 设置下一个传花人 */ public void setPlayer(Player player) { this.player = player; } /** 将花传给下一家,如果没有就结束 */ public void next(int index) { if (player != null) { player.handlerRequest(index); } else { System.out.println("传花结束"); } } }
参与击鼓传花的人:
public class JiaMu extends Player { public JiaMu(Player player) { this.setPlayer(player); } @Override public void handlerRequest(int index) { if (index == 1) { System.out.println("贾母执行酒令"); } else { System.out.println("贾母将花传给下一个"); next(index); } } }
public class JiaShe extends Player { public JiaShe(Player player) { this.setPlayer(player); } @Override public void handlerRequest(int index) { if (index == 2) { System.out.println("贾赦执行酒令"); } else { System.out.println("贾赦将花传给下一个"); next(index); } } }
public class JiaZheng extends Player { public JiaZheng(Player player) { this.setPlayer(player); } @Override public void handlerRequest(int index) { if (index == 3) { System.out.println("贾政执行酒令"); } else { System.out.println("贾政将花传给下一个"); next(index); } } }
public class JiaBaoYu extends Player { public JiaBaoYu(Player player) { this.setPlayer(player); } @Override public void handlerRequest(int index) { if (index == 4) { System.out.println("贾宝玉执行酒令"); } else { System.out.println("贾宝玉将花传给下一个"); next(index); } } }
public class JiaHuan extends Player { public JiaHuan(Player player) { this.setPlayer(player); } @Override public void handlerRequest(int index) { if (index == 5) { System.out.println("贾环执行酒令"); } else { System.out.println("贾环将花传给下一个"); next(index); } } }
击鼓者:
public class DrinkingGame { static private Player player; public static void main(String[] args) { player = new JiaMu( new JiaShe( new JiaZheng( new JiaBaoYu( new JiaHuan(null))))); //设置第四个执行酒令 player.handlerRequest(4); } }
类图: