原文链接:传送门。
这篇文章是关于在.NET Core中使用中介者模式系列的第一部分。这是一个很好的可以开始的地方。
几年前,我曾经帮助建立一个完全以“中介者模式”构建的工程。或者更明确的说,其完全是使用 MediatR 库建立的。那里具有关于中介者模式背后的理论的所有表示以及其如何成为一种真正全新的思考方式。我禁不住的思考……我们已经做它做了好几年了。然而我们仅仅称之为好的程序,事实上在第二部分我们会看到我有自己的模式,我称之为“IEnumerable Pattern”,其能够达到相同的事情。
但是最终将它们全部记录下来却花费了这么多年的时间。因此它在这儿。这儿便是C#中的中介者模式(或者更明确的说,在.NET Core中的中介者模式)。
中介者模式的定义
实际上,中介者模式最早可以追溯到1994年的那本著名的书中:“Design Patterns: Elements of Reusable Object-Oriented Software”。但我觉得它只是最近才重新出现,因为有很多库试图实现这个模式。
在一个果壳中,其定义为(就像是从维基百科上窃取的一样):
中介者模式的本质是“定义了一个封装了一系列对象是如何交互的对象”。其通过使得对象之间减少相互显示涉及而促进了松耦合,并且其允许它们之间的交互独立的发生变化。客户端类可以使用中介者来发送消息给其他客户端类,并且可以通过一个中介者类的事件从其他客户端接收消息。
现在,让我们将其稍稍分解为两个点,稍后我们会讲到它们:
- 其是一个封装了对象如何交互的对象。所以它显然能够处理对象之间的消息传递。
- 其通过不使得对象之间相互引用而促进了松耦合,而是通过中介者。因此它们将消息传递给中介者,然后中介者会将消息传递给正确的人。
说真的,这就是中介者模式的全部。
当你孤立地思考这两个要点时。听起来像是一个信息中心,对吧?那是因为…其实有点像。它就像代码中的消息中心。当您通过一个典型的消息中心发送消息时,您不知道谁在接收该消息,您只需知道集线器知道并且它会为您进行分类。
可视化表现
如果我们使用我极其有限的图标技能将其分解为可视化图表,它看起来有点像这样:
很可能这是一个中介者模式的简化版本。因为中介者模式允许双向通信,其不只是一个单向广播。但是我认为这是我们在后续的例子中将要尝试并且使用的模型。
为什么?
最后,是“为什么“? 为什么这是一件事情?
如果我们继续看上面的图表,如果我们使得MyService直接调用其他Handlers(举个例子,通知它们一个Action),那么当我们增加Handler时,MyService不得不涉及到它们所有的Handlers,即使其并不关心结果是什么。举个例子,我们的服务或许开始的时候看起来像是这样:
class MyService { private readonly Handler1 _handler1; private readonly Handler2 _handler2; private readonly Handler3 _handler3; public MyService(Handler1 handler1, Handler2 handler2, Handler3 handler3) { _handler1 = handler1; _handler2 = handler2; _handler3 = handler3; } public void DoSomething() { //Do something here. //And do some more work //And then notify our handlers. _handler1.Notify(new HandlerArgs()); _handler2.Notify(new HandlerArgs()); _handler3.Notify(new HandlerArgs()); } }
因此,当我们额外增加一个Handler时候会发生什么?当我们移除Handlers又会发生什么呢?当在实际中我们的服务真的不需要关心谁会接到通知时,我们的服务会保持变化。
使用”中介者模式“,它或许会最终看起来像是这样:
class MyService { private HandlerMediator _handlerMediator; public MyService(HandlerMediator handlerMediator) { _handlerMediator = handlerMediator; } public void DoSomething() { //Do something here. //And do some more work //And then notify our handlers. _handlerMediator.Notify(new HandlerArgs()); } } class HandlerMediator { private readonly Handler1 _handler1; private readonly Handler2 _handler2; private readonly Handler3 _handler3; public HandlerMediator(Handler1 handler1, Handler2 handler2, Handler3 handler3) { _handler1 = handler1; _handler2 = handler2; _handler3 = handler3; } public void Notify(HandlerArgs handlerArgs) { _handler1.Notify(handlerArgs); _handler2.Notify(handlerArgs); _handler3.Notify(handlerArgs); } }
因而我们得到的好处便是,当Handlers变化时候,不论是增加还是减少,服务本身不会变化。然而其还是有一点不好的便是我们或许是将负载转移给了中介者。它(中介者)的工作现在是管理Handlers以及它们如何被通知。但是这是有道理的。有一个其单独的工作是通知客户端的类,便应该能够根据客户端需要的通知方式进行更改。而我们的服务实际上不关心那些处理程序的实现细节,它可以继续工作。
也就是说,后续我们会看到我们如何使用DI来帮助我们减少两者的负载,并仍然坚持中介者模式的核心。
下一步
在这个系列的下一篇文章中,我们将看一个设计模式,我称之为”IEnumerable Pattern“。它本质上是带有一些依赖注入的中介者模式。