装饰器模式可以替换为行为模式来解决问题吗?

时间:2019-03-22 06:40:24

标签: java design-patterns architecture

我已经阅读并看到了许多描述装饰器为何是结构模式的示例。以及它如何构成对象以添加新功能。 访客模式有助于向对象添加新功能。策略模式是在运行时交换算法。

我仍然无法理解为什么装饰器模式是结构性模式而不是行为模式的概念。

有人可以用一些实际的编程示例来说明这些模式吗?比萨饼和飞鸭的例子让我觉得自己理解了,但是一段时间之后,我才刚读完。

进行真正的系统设计,陷入较小的问题并应用所有这些设计模式将非常有帮助。

编辑:采取以下用例来应用和理解不同的设计模式。请分享您对此示例的想法。

博物馆的语音交互系统,孩子们可以问任何问题并获得有关它的信息并预订任何演出的门票。 例如:孩子问什么是太阳系,然后深入研究有关行星的问题。然后预订天文馆表演的门票。

以下是可以应用设计模式的技术用例。请帮助为每种情况选择正确的设计模式: 1)听孩子的问题并从中解析数据。 2)识别孩子是否在询问信息或要求指示或想预订机票等... 3)根据孩子的意图,给出答案或收集更多信息以预订票或安排团体旅游。 4)管理对话和上下文数据。 5)调用API以获得答案或预订游览。

想要应用设计模式,以便系统可以遵循SOLID原则。 上述每个用例的设计要求: 1)在不修改现有代码的情况下,系统应遵循OCP接受新的输入法(触摸,语音,键盘,鼠标)。当孩子问问题时,也可以接受新的传感器输入,例如面部反应。 2)系统应该可扩展以支持新的用户意图。 3)有些问题有直接的答案,有些情况需要跟进问题,以便从孩子那里获得更多详细信息(书籍参观)。在这里,每次对话都做类似的事情(听孩子,系统做某事,用跟进或回答来回应孩子)。可以在这里使用装饰器设计模式来组合对象,例如父对象(以获取孩子想要做的事情)和子对象(以获取后续详细信息来预订游览) 4)应该能够重用相同的设计来管理来回问题的任何流程并管理上下文数据。 5)松散地耦合API,根据需要交换API,支持来自不同提供商的API以预订导览,回答问题等(策略模式?)。如果涉及多个API竞争预定行程,并且系统选择了一个API,那将是一个很好的使用模式。

该系统应该可扩展,以支持新的用例,例如“向博物馆员工寻求帮助”或“从美食广场购买咖啡”或“报名参加志愿者”。

不确定此论坛是否支持这种讨论。但是我找不到更好的论坛来进行讨论。

1 个答案:

答案 0 :(得分:0)

行为设计模式与对象的交互和责任有关。在这些设计模式中,对象之间的交互作用应使它们能够轻松地彼此交谈,并且仍然保持松散耦合。根据您的情况,访问者可让您在对象结构上定义新操作,而无需更改对其进行操作的元素的类。

另一方面,结构设计模式与如何组合类和对象以形成更大的结构有关。 这是灵活的结构

interface Executable {

    void execute();

}

class DeleteUser implements Executable {

    @Override
    public void execute() {
        // delete
    }

}

class LoggingExecutable implements Executable {

    private final Executable executable;

    @Override
    public void execute() {
        // log before
        executable.execute();
        // log after
    }

}

class TransactionalExecutable implements Executable {

    private final Executable executable;

    @Override
    public void execute() {
        // open transaction
        try {
            executable.execute();
        } catch (FooException e) {
            // rollback
        } finally {
            // close transaction
        }
    }

}

这里是使用装饰器的假设复合结构。如您所见,它是灵活的结构。我可以构造既可以记录日志又可以进行事务处理的Executable,但是我可以随意使用它来记录日志或使用完全不同的东西进行修饰。

new LoggingExecutable(
    new TransactionalExecutable(
        new DeleteUser()));

new LoggingExecutable(
    new DeleteUser());