事件,代表或接口?

假设我有一个Monkey类,有时需要获取Banana的一个实例。 提供这种香蕉的方式对猴子不感兴趣,但它确实启动了香蕉采集。

现在我至少有三种方法可以将我的猴子送到香蕉供应商那里。 最好的方法是什么?

1.事件

举起一场Monkey.BananaNeeded活动。 事件处理程序设置BananaNeededEventArgs.Banana属性。

2.界面

调用IBananaProvider.GetBananaIBananaProvider实例作为构造函数参数或通过属性注入IBananaProvider

3.代表

调用System.Func类型的委托。 委托作为构造函数参数或通过属性注入Monkey中。 这个很诱人,因为它不需要声明任何额外的接口或类,但显然它不是一个受欢迎的选择。

我不喜欢事件和委托选项,除非有一种机制来确保不会附加多个处理程序。 因此,选项2是IMO的赢家。

如果有几个可能的香蕉供应商,事件模型效果最好,即猴子要求所有供应商轮流提供香蕉,第一个可以提供一个香蕉供应商。

另外两个型号适用于每只猴子一个香蕉certificate器。 委托更容易为其创建提供程序,并且界面更加结构化。

上述场景中最好的方法是使用Interface。 在OOAD术语中,我们可以定义上面的场景,因为Monkey类有一个香蕉。

我通常使用2。

 IBananaProvider bananaProvider = ProviderFactory.Get(); 

Monkey上有一些操作需要香蕉。

猴子获得香蕉的需要是这些操作。 你肯定可以通过香蕉作为操作的参数。

我将删除Money对IBananaProvider的依赖性。

 class Monkey { void FeedWith(Banana banana) { ... } } 

得到香蕉而不是猴子是呼叫者的责任。

我在这里主张不在实体中注入服务。

理想情况下,dependency injection是更普遍接受的方法。

另一种尝试方法是消息队列

在这种情况下, Monkey基本上可以将消息“发布”到某个队列以获得美味的香蕉。 这种“发布”将触发一些正在监视队列的提供者,然后完成请求 – 提供者的实际实例响应是无关紧要的。 然后Monkey会等待对原始消息的响应,并在感兴趣的包裹从BananaProvider到达时采取行动。

消息队列将提供者和使用者分离。 当然,仍有某种forms的合同“到位,但在请求的另一端,答案是无关紧要的。

我同意并说选项2是最好的解决方案。 代表通常意味着,委托一些东西,换言之做某事,而事件是为了对发生的事情做出即时反应,通常是与用户有关。 界面简单地说,“这就在这里,你可以做到。” 因为您不希望香蕉或猴子一开始做任何事情,并且您不希望用户直接与代码的内部工作进行交互,所以界面会赢得它。 你所需要的只是知道猴子可以收到香蕉。 他之后决定用那些香蕉做的事取决于他,香蕉本身以及周围的代码不应该关注它。