设计决策 - 工厂模式 vs 观察者模式

3
我有以下情形:
我有一个QueueReader类,它将从队列中读取消息。我还有一些发送器,如EmailSender和SMSSender,它们将使用电子邮件或SMS向客户发送这些消息。未来可能会添加更多的发送器。
我可以想到两种方法来做这个,我不确定哪一个更有利。
工厂模式:
我可以拥有一个SenderManager,它将使用SenderFactory来创建适当的发送器,然后调用其Send()方法。
因此,QueueReader在读取消息时将调用SenderManager的Send(),该方法将执行以下操作:
IMySender sender = SenderFactory.CreateSender()
sender.Send()

//I have the information to create the proper Dispatcher in the 
//factory based upon the message but I have omitted it for brevity.

所以,现在如果我要添加一个新的发送者,我不需要更改QueueReader或SenderManager。我只需添加新的发送者并修改SenderFactory即可。
观察者模式 与上述相反,我可以让QueueReader类实现NewMessage事件,然后让所有我的发送者订阅此事件。发送者将可以访问上面工厂中的信息,以了解消息是否适用于它们。
这样做的好处是任何新的发送者只需订阅该事件即可。
现在我已经把所有这些写下来,我认为观察者模式是更清晰的方法...
但是,如果有人有任何见解或建议,请分享。
谢谢!

如果发送者取决于消息类型,为什么不将“Send”方法移动到您的“Message”类型中呢?或者至少向其中添加一个“GetSender”方法? - stakx - no longer contributing
1
你真正想要的是依赖注入(DI)。如果你真的知道自己想要什么,你可以很容易地通过 DI 来解决这个问题。你可以传递一个接口给你的队列读取器,而不是一个具体的实现。此外,你还可以进行一些后期绑定,并让容器在运行时决定注入什么。 - DarthVader
@stakx 因为 SRP 原则... QueueReader 不应该发送消息。这有意义吗? - Ali
它确实如此,但同时,如果某些行为取决于对象的类型,则面向对象的解决方案是在该类型中定义它 - 否则您可能会遇到类似 if (x is Foo) DoFoo(x); else if (x is Bar) DoBar(x); else if ... 的代码。无论如何,如果您不想在消息类型中直接使用 Send,我建议使用 DI。 - stakx - no longer contributing
2个回答

3

我建议采用混合模式:

SenderManager(观察者)监听传入的消息并选择正确的发送器(如果需要,可以向SenderFactory请求创建一个)。这有两个好处:

首先,您可以控制选择哪个发送器(不需要公开SenderManager类),避免中间人攻击。如果您将暴露API以供其他开发人员实现其自己的发送器,则尤其重要。

其次,您可以实现一种类似于垃圾回收器的机制,并处理不再需要的发送器,而不是实例化多个发送器来监视您的流程。

您需要某种注册函数来将发送器注册到SenderManger中。

如果使用ObserverPattern,请不要忘记实现默认发送器(可以是日志系统),以处理不需要的消息。


0

如果您想根据特定标准创建实例,工厂模式会很好。

如果您确定将使用短信或电子邮件发送器,则可以考虑使用依赖注入,并使用任何DI容器在运行时解析IMySender。例如,StructureMap

我不确定观察者模式,似乎有点复杂。


没有观察者不复杂。你也可以将其注入到观察者中。 - DarthVader

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接