首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >责任链与案件陈述

责任链与案件陈述
EN

Stack Overflow用户
提问于 2015-12-10 14:42:30
回答 1查看 1.1K关注 0票数 3

当我阅读关于责任链的文章时,它谈到了如何将客户端与数据的实际处理分离开来。因此,它表示客户端程序调用链的第一个成员,该成员决定是否可以处理请求,如果可以,则处理请求,如果不能,则调用链的下一个成员,以此类推。

我已经读到,可以将更多的成员添加到链中,并且客户端程序并不需要实际更改来处理这个问题。我在包括Wikipedia在内的例子中看到的是,客户端必须实例化链的每个成员,甚至为链的每个成员设置后继者。

如果链中的对象的顺序是由客户端决定的,而客户机甚至必须实例化链中的每个对象,这又如何被认为是松散耦合呢?

EN

回答 1

Stack Overflow用户

发布于 2015-12-10 22:05:11

责任链比case语句灵活得多。重要的是,CoR可以:

处理请求时不需要硬连接处理程序关系和优先级,或者请求到处理程序映射。

这意味着客户端不知道任何后续处理程序,甚至不知道链的存在。

处理程序对象的数量和类型并不事先就知道,它们可以动态配置。

这意味着可以在运行时添加新的处理程序,并且可以重新排序现有的处理程序。

一个更基本的答案是,case语句是一个程序性结构,因此通常不用于面向对象的编程,例如四人帮设计模式。

为了简单起见,在线示例可能倾向于在客户机中配置CoR;但在实践中,这违背了模式的目的,因此CoR将在其他地方配置。玩具示例的目的仅仅是显示一个链的外观和它在实例化后是如何工作的;但是在哪里实例化它是选择CoR的动机的关键。

示例:客户端依赖于服务来处理字符串值。

服务API是微不足道的。

代码语言:javascript
复制
interface StringHandler {
    void handle(String arg);
}

客户端可能是无限复杂的,但在某个时候它会调用服务。

代码语言:javascript
复制
class Client {
    private final StringHandler argHandler;

    Client(StringHandler argHandler) {
        this.argHandler = argHandler;
    }

    void method(String arg) {
        argHandler.handle(arg);
        // more business logic...
    }
}

我们选择将服务作为一条责任链来实施。

代码语言:javascript
复制
class ChainedHandler implements StringHandler {
    private final String handledString;
    private ChainedHandler next;

    ChainedHandler(String handledString) {
        this.handledString = handledString;
    }

    Optional<ChainedHandler> next() {
        return Optional.ofNullable(next);
    }

    ChainedHandler next(ChainedHandler handler) {
        ChainedHandler subsequent = next;
        next = handler;
        if (handler != null && subsequent != null)
            handler.next(subsequent);
        return this;
    }

    @Override
    public void handle(String arg) {
        if (arg.equalsIgnoreCase(handledString)) {
            System.out.println("Handled: " + arg);
        } else {
            next().ifPresentOrElse(
                    handler -> handler.handle(arg),
                    () -> System.out.println("No handler for: " + arg));
        }
    }
}

因此,我们构建了一个链,将其连接到客户端,并通过修改链来执行一些场景。

代码语言:javascript
复制
public static void main(String... commandLineArgs) {
    List<String> args = commandLineArgs.length > 0
            ? Arrays.asList(commandLineArgs)
            : List.of("foo", "bar", "baz", "qux");

    ChainedHandler chain = new ChainedHandler("foo")
            .next(new ChainedHandler("bar")
            .next(new ChainedHandler("baz")));

    Client client = new Client(chain);
    args.forEach(client::method);
    System.out.println();
    
    chain.next(new ChainedHandler("qux"));
    args.forEach(client::method);
    System.out.println();
    
    chain.next(null);
    args.forEach(client::method);
}

注意,Client不知道存在一个链。此外,请注意,没有编辑代码就修改了链。这就是GoF所指的解耦。case语句或if/else块不能提供相同的灵活性。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34204740

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档