Jos*_*son 9 php oop design-patterns symfony1
我想通过使某些类可观察来促进我的PHP代码中的松散耦合.Symfony的EventDispatcher组件看起来很有前途,SPL SplObserver/SplSubject对也是如此.
最好的方法是什么?我可以看到几种不同的可能性:
(1)将EventDispatcher实例注入每个可观察类(跟踪全局EventDispatcher实例):
class Foo
{
    public function __construct($dispatcher)
    {
        $this->dispatcher = $dispatcher;
    }
    public function bar()
    {
        $this->dispatcher->dispatch(...);
    }
}
(2)让observable类扩展EventDispatcher类:
class Foo extends EventDispatcher
{
    public function bar()
    {
        $this->dispatch(...);
    }
}
(3)使用SplObserver/SplSubject - 直截了当,但不如EventDispatcher组件灵活
rdl*_*rey 48
免责声明:这个答案与Symfony EventDispatcher无关,而是与您的问题有关.如果你只是想要一个答案,你可以跳过(有点)学术讨论并跳到最后.
事实:增加应用程序的大小意味着复杂性的一致性增加.
随着应用程序范围的扩大,您会发现自己添加了越来越多的类来实现必需的功能.突然之间,记住对象在创建Foo对象时需要执行某些特定操作并不容易Bar.此外,当您的对象开始为彼此提供互补功能时,维持必要的关系变得越来越困难而不会使用非常紧密耦合的对象.
我们需要一种方法来让对象进行通信,而无需硬编码显式引用,当事情发生变化时我们会忘记改变.那么我们如何在快速增长的对象图的节点之间管理这种相互关联的功能呢?
让我们稍微绕道一下,考虑一个浪漫的比喻......
任何关系都需要一致的沟通,如果它将持续.当然,你和你的伴侣可以在星期六晚上聚在一起进行阴暗的连接,而不是在一周剩下的时间里互相交谈.然而,这种类型的沟通通常会导致脆弱的关系,在这种关系中,任何一方都不了解对方实际需要在关系的背景下运作良好的东西.
继续这种类比,随着你的个性随着时间的推移而缓慢变化(并且它会),这种缺乏沟通会阻止你的伴侣理解如何最好地与你互动.最终,所有破碎的承诺和未接来电都成了头,这种关系再也不起作用了.它坏了.
您的应用程序以相同的方式工作.代码应该足够成熟,可以说:"嘿宝贝,我可能会改变,但如果我这样做,我保证我会永远让你知道我发生了什么." 遗憾的是,随着复杂性的增加,传统的直线应用程序设计使得在没有类之间紧密耦合的情况下难以维护此通信
这就是事件管理的全部意义所在.目标是为我们的对象提供一种彼此通信的方式,这种方式不会与需要与之通信的对象进行硬编码关系.与大多数编程问题一样,没有一种单一,具体,"正确"的方法来实现这一点.你的问题特别提到了两种可行的方法,所以我会解决这些问题.如果你想了解其他一些选项,@ ircmaxell最近发布了一篇很好的调查博客文章,关于使PHP应用程序"可插拔".
实际上,你会发现Observer模式的实际PHP应用程序很少.这是因为如果您希望您的代码非常动态,那么在您将观察者附加到所有地方的主题对象之前不需要很长时间.
当发生这种情况时,你已经开始尝试实现松散耦合,但是你已经创建了一个不同类型的问题:手动附加所有观察者和主体.例如,如果应用程序中的每个类都是Logger观察者对象的主体,那么您已经为自己创建了大量工作.此外,恕我直言这种方法有时会通过移动可能更准确地描述为主题构造函数的方法签名之外的主题的实际依赖性的东西来模糊您的API.
如果我们使用集中式调度程序在事件发生时通知感兴趣的对象,我们的应用程序将更加灵活,尽管Observer模式可以是一次性或简单情况的理想选择.
管理事件的更健壮的方法是插入一个集中层来处理调度事件到适当的侦听器.这就是Mediator wiki模式(以及Symfony事件调度程序)所做的事情.
Mediator的重点在于它是系统中每个事件的集中式中转站,因此需要在整个应用程序范围内(或者介导的部分)访问它.请注意,这并不意味着您应将其视为全局变量,并使用全局关键字无条件地访问Mediator,或将其包装在某种邪恶的单例对象或静态属性/方法中.这种滥用将导致@liquorvicar在第一个答案中提出的问题.但是,我强烈不同意该答案的评估:
"拥有一个eventDispatcher,它在你的应用程序的任何地方,几乎所有东西都可以使你的代码更难以测试/理解/维护等(它可以接近上帝的对象)"
只有在您滥用调解员的情况下才会这样; 它应该发送事件通知而不是其他任何东西.因为这个原因,我会提醒你不要像你在问题的选项(2)中建议的那样扩展它.正确使用时,中介对象极其可测试.没有什么比模拟构造函数中指定的依赖项对象的行为更简单了.这就是单元测试的全部意义所在.
因此,如果您在应用程序中需要非线性事件管理,我强烈建议您从问题中选择(1).只要你不滥用它,这是完全可以接受的.对Symfony实现进行着色,似乎支持任何PHP可调用作为监听器.就个人而言,我更喜欢一个系统,它允许基于类的侦听器的惰性实例化,以实现更高效和面向对象的范例,但实现细节由您自己决定.
责任链模式与中介密切相关,是实现类似结果的另一种有效方法.如果您有兴趣,我建议先前发布@ ircmaxell博客文章中的链接.
| 归档时间: | 
 | 
| 查看次数: | 3822 次 | 
| 最近记录: |