责任链模式定义:
阎宏的定义:"发出这个请求的客户端并不知道链上的那一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任."
阎宏的定义很精炼,但是太精炼的以至于很多人很难理解。
定义分解如下:
1 服务端有一组策略(也可以称之为方法,算法等等)按顺序处理请求。这组策略的组织顺序与客户端无关。
2 当这组策略中的某一个策略满足结束条件时,整个责任链结束。
解释:责任链模式可以被认为是“策略对象顺序执行”。在一个顺序策略链表中的策略按顺序被调用。当某种策略满足要求,就返回成功标志或者责任链结束。
注意的是Gof的例子没有使用链表。
这个例子非常好的揭示了责任链模式的奥秘:
//: chainofresponsibility:FindMinima.javaimport junit.framework.*;class Arrays2 { public static String toString(double[] a) { StringBuffer result = new StringBuffer("["); for(int i = 0; i < a.length; i++) { result.append(a[i]); if(i < a.length - 1) result.append(", "); } result.append("]"); return result.toString(); } }
// Carries the result data and // whether the strategy was successful: class LineData { public double[] data; public LineData(double[] data) { this.data = data; } private boolean succeeded; public boolean isSuccessful() { return succeeded; } public void setSuccessful(boolean b) { succeeded = b; } }
interface Strategy { LineData strategy(LineData m); }
class LeastSquares implements Strategy { public LineData strategy(LineData m) { System.out.println("Trying LeastSquares algorithm"); LineData ld = (LineData)m; // [ Actual test/calculation here ] LineData r = new LineData( new double[] { 1.1, 2.2 }); // Dummy data r.setSuccessful(false); return r; } }
class NewtonsMethod implements Strategy { public LineData strategy(LineData m) { System.out.println("Trying NewtonsMethod algorithm"); LineData ld = (LineData)m; // [ Actual test/calculation here ] LineData r = new LineData( new double[] { 3.3, 4.4 }); // Dummy data r.setSuccessful(false); return r; } }
class Bisection implements Strategy { public LineData strategy(LineData m) { System.out.println("Trying Bisection algorithm"); LineData ld = (LineData)m; // [ Actual test/calculation here ] LineData r = new LineData( new double[] { 5.5, 6.6 }); // Dummy data r.setSuccessful(true); return r; } }
class ConjugateGradient implements Strategy { public LineData strategy(LineData m) { System.out.println( "Trying ConjugateGradient algorithm"); LineData ld = (LineData)m; // [ Actual test/calculation here ] LineData r = new LineData( new double[] { 5.5, 6.6 }); // Dummy data r.setSuccessful(true); return r; } }
class MinimaFinder { private static Strategy[] solutions = { new LeastSquares(), new NewtonsMethod(), new Bisection(), new ConjugateGradient(), }; public static LineData solve(LineData line) { LineData r = line; for(int i = 0; i < solutions.length; i++) { r = solutions[i].strategy(r); if(r.isSuccessful()) return r; } throw new RuntimeException("unsolved: " + line); } } public class FindMinima extends TestCase { LineData line = new LineData(new double[]{ 1.0, 2.0, 1.0, 2.0, -1.0, 3.0, 4.0, 5.0, 4.0 }); public void test() { System.out.println(Arrays2.toString( ((LineData)MinimaFinder.solve(line)).data)); } public static void main(String args[]) { junit.textui.TestRunner.run(FindMinima.class); } } ///:~
|