企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
### 责任链模式 *责任链模式* 也许可以被看作一个使用了 *策略* 对象的“递归的动态一般化”。此时我们进行一次调用,在一个链序列中的每个策略都试图满足这个调用。这个过程直到有一个策略成功满足该调用或者到达链序列的末尾才结束。在递归方法中,一个方法将反复调用它自身直至达到某个终止条件;使用责任链,一个方法会调用相同的基类方法(拥有不同的实现),这个基类方法将会调用基类方法的其他实现,如此反复直至达到某个终止条件。 除了调用某个方法来满足某个请求以外,链中的多个方法都有机会满足这个请求,因此它有点专家系统的意味。由于责任链实际上就是一个链表,它能够动态创建,因此它可以看作是一个更一般的动态构建的 `switch` 语句。 在上面的 `StrategyPattern.java` 例子中,我们可能想自动发现一个解决方法。而 *责任链* 就可以达到这个目的: ```java // patterns/chain/ChainOfResponsibility.java // Using the Functional interface // {java patterns.chain.ChainOfResponsibility} package patterns.chain; import java.util.*; import java.util.function.*; class Result { boolean success; List<Double> line; Result(List<Double> data) { success = true; line = data; } Result() { success = false; line = Collections.<Double>emptyList(); } } class Fail extends Result {} interface Algorithm { Result algorithm(List<Double> line); } class FindMinima { public static Result leastSquares(List<Double> line) { System.out.println("LeastSquares.algorithm"); boolean weSucceed = false; if(weSucceed) // Actual test/calculation here return new Result(Arrays.asList(1.1, 2.2)); else // Try the next one in the chain: return new Fail(); } public static Result perturbation(List<Double> line) { System.out.println("Perturbation.algorithm"); boolean weSucceed = false; if(weSucceed) // Actual test/calculation here return new Result(Arrays.asList(3.3, 4.4)); else return new Fail(); } public static Result bisection(List<Double> line) { System.out.println("Bisection.algorithm"); boolean weSucceed = true; if(weSucceed) // Actual test/calculation here return new Result(Arrays.asList(5.5, 6.6)); else return new Fail(); } static List<Function<List<Double>, Result>> algorithms = Arrays.asList( FindMinima::leastSquares, FindMinima::perturbation, FindMinima::bisection ); public static Result minima(List<Double> line) { for(Function<List<Double>, Result> alg : algorithms) { Result result = alg.apply(line); if(result.success) return result; } return new Fail(); } } public class ChainOfResponsibility { public static void main(String[] args) { FindMinima solver = new FindMinima(); List<Double> line = Arrays.asList( 1.0, 2.0, 1.0, 2.0, -1.0, 3.0, 4.0, 5.0, 4.0); Result result = solver.minima(line); if(result.success) System.out.println(result.line); else System.out.println("No algorithm found"); } } /* Output: LeastSquares.algorithm Perturbation.algorithm Bisection.algorithm [5.5, 6.6] */ ``` 我们从定义一个 `Result` 类开始,这个类包含一个 `success` 标志,因此接收者就可以知道算法是否成功执行,而 `line` 变量保存了真实的数据。当算法执行失败时, `Fail` 类可以作为返回值。要注意的是,当算法执行失败时,返回一个 `Result` 对象要比抛出一个异常更加合适,因为我们有时可能并不打算解决这个问题,而是希望程序继续执行下去。 每一个 `Algorithm` 接口的实现,都实现了不同的 `algorithm()` 方法。在 `FindMinama` 中,将会创建一个算法的列表(这就是所谓的“链”),而 `minima()` 方法只是遍历这个列表,然后找到能够成功执行的算法而已。