1

我正在构建一个开源库,我可以总结如下:

class SuperThing {
    public function doStuff($object) {
        // ...
    }
}

我想为库的用户提供添加自定义行为的可能性。

例如,他可能想在操作中的特定点插入一些日志记录,或者他可能想在某个点修改对象。

我看到了两种方法:

  • 模板方法模式似乎很合适,但它会迫使我添加很多受保护的方法(比如beforeDoingThingA()afterDoingThingA()...),它会迫使库的用户扩展我的类以添加他的行为。

  • 使用事件:SuperThing::doStuff()引发事件,用户可以注册到任何他想要的。

对我来说,使用事件似乎更简单、更清晰、更易于维护......

但在我看来,事件主要是关于发送发生某事的消息。不允许有人“钩”入操作并修改某些对象。也许我错了。

那么事件是否适合这种情况?如果没有,是否有模板方法模式的替代方案?

4

2 回答 2

0

订阅事件应该是可选的;如果您对此感到满意,那么他们是有可能的。

每次我实现了模板方法模式,我都后悔了。它假设图书馆的客户(通常是我的更高版本)总是想要:

DoA();
// do some hardcoded or non-virtual stuff
DoB();
// ...
DoC();

不可避免地,我想改变 A、B 和 C 的顺序,改变硬编码的东西,或者我(或其他开发人员)在编写模板时没有想到的其他东西。我正在尝试编写 Open-Closed 代码,但我经常失败。

使用小组件并组合它们是另一种选择;依赖注入是另一个。第三个是更倾向于函数式编程并将委托或函数指针传递给方法,或组合函数。每个选项都有其优点和缺点;我认为没有一个正确的答案。

于 2013-09-19T17:21:29.873 回答
0

您始终可以组合多种模式。在这个例子中,为什么不同时提供一个事件系统和模板方法呢?这样,用户可以选择一个或另一个(或两者)来做他们想做的事。

但是,根据您在做什么,模板方法可能还不够。我经常发现如果我正在制作一个“管道”,我会编写小的可互换组件,用户可以将这些组件以各种组合串在一起以执行他们想要的操作,并且还可以监听管道运行时触发的事件。

管道非常简单,它只是按照提供的顺序执行组件(所以我猜这就是命令模式),并且管道和组件都可以向侦听器触发事件​​。

于 2013-09-19T19:20:39.217 回答