Chain Of Responsibility?
这种情况下,我们可以考虑将多个对象组成一条职责链,然后按照它们在职责链上的顺序一个一个地找出到底应该谁来负责处理。
通俗:她告诉我们应该去“营业窗口”。然后等我们到了“营业窗口”后,又被告知应该去“售后部门”。等我们好不容易赶到了“售后部门”,又被告知应该去“资料中心”,因此最后我们又不得不赶往“资料中心”。像这样,在找到合适的办事人之前,我们被不断地踢给一个又一个人,这就是“推卸责任”。
理解职责
理解好责任链设计模式关键在于 SolveAnswer是处理者而NoSolve、LimitSolve、OddSolve、SpcialSolve才是具体的处理者。
在SolveAnswer用模版设计的模式定义遇到解决问题的策略办法,能解决就在当前实现的解决方法的子类进行解决,不能解决就在继续向下面的责任类继续传递。|名字 +++++++++++++++++++++++++++++++说明
|Question|表示发生的问题的类。它带有问题编号(number)
SolveAnswer用来解决问题的抽象类
NoSolve用来解决问题的具体类(永远“不处理问题”)
LimitSolve用来解决问题的具体类(仅解决编号小于指定编号的问题)
OddSolve|用来解决问题的具体类(仅解决奇数编号的问题)
SpcialSolve用来解决问题的具体类(仅解决指定编号的问题)
MainT 制作SolveAnswer的职责链,制造问题并测试程序行为比较重要的话: Chain of Responsibility模式的最大优点就在于它弱化了发出请求的人(Client角色)和处理请求的人(ConcreteHandler角色)之间的关系。Client角色向第一个ConcreteHandler角色发出请求,然后请求会在职责链中传播,直到某个ConcreteHandler角色处理该请求。
如果不使用该模式,就必须有某个伟大的角色知道“谁应该处理什么请求”,这有点类似中央集权制。而让“发出请求的人”知道“谁应该处理该请求”并不明智,因为如果发出请求的人不得不知道处理请求的人各自的责任分担情况,就会降低其作为可复用的组件的独立性。需要知道的技术点:
使用Chain of Responsibility模式可以推卸请求,直至找到合适的处理请求的对象,这样确实提高了程序的灵活性,但是会有一定的处理延迟:当然你也可以通过算法来定义处理的特殊路径,但是未免太多余麻烦:所以有的时候我们不如直接显示调用来提高灵活性。
UML
时序图:
Code
- Question :
public class Question { private int question_number; public Question(int question_number) { this.question_number = question_number; } public int getQuestion_number() { return question_number; } @Override public String toString() { return "Question{" + "question_number=" + question_number + '}'; } }
- SolveAnswer
public abstract class SolveAnswer { private String Solve_Name; // 继承链者 private SolveAnswer next; public SolveAnswer(String solve_Name) { Solve_Name = solve_Name; } /** * 设置需要推卸责任的对象 */ public SolveAnswer setNext(SolveAnswer solveAnswer){ this.next=solveAnswer; return next; } /** * 解决问题的步骤 */ public final void support(Question question){ if(solve(question)){ finish(question); }else if(next!=null){ this.next.support(question); }else{ fail(question); } } /** * 交给子类取解决 * @param question * @return */ protected abstract boolean solve(Question question); /** * * @param question */ private void finish(Question question) { System.out.println(question+"能被解决"+this.toString()+"."); } /** * * @param question */ private void fail(Question question) { System.out.println(question+"不能被解决."); } @Override public String toString() { return "["+this.solve_Name+ "]"; } }
- NoSolve SpcialSolve OddSolve LimitSolve
public class LimitSolve extends SolveAnswer { private int limit; public LimitSolve(String solve_Name,int limit) { super(solve_Name); this.limit=limit; } @Override public boolean solve(Question question) { if(question.getQuestion_number()<limit){ return true; }else{ return false; } } } public class NoSolve extends SolveAnswer{ public NoSolve(String solve_Name) { super(solve_Name); } @Override public boolean solve(Question question) { return false; } } public class OddSolve extends SolveAnswer { public OddSolve(String solve_Name) { super(solve_Name); } @Override public boolean solve(Question question) { if(question.getQuestion_number()%2==1){ return true; }else{ return false; } } } public class SpcialSolve extends SolveAnswer { private int special; public SpcialSolve(String solve_Name,int specalNum) { super(solve_Name); this.special=specalNum; } @Override public boolean solve(Question question) { if(question.getQuestion_number()==special){ return true; }else { return false; } } }
- MainT 测试
public class MainT { public static void main(String[] args) { SolveAnswer tom=new NoSolve("cat1"); SolveAnswer tom2=new LimitSolve("cat2",100); SolveAnswer tom3=new OddSolve("cat3"); //只能解决225问题 SolveAnswer tom4=new SpcialSolve("cat4",225); tom.setNext(tom2).setNext(tom3).setNext(tom4); for (int i = 0; i < 300; i+=3) { tom.support(new Question(i)); } } }