依赖注入系统中的事件会走哪条路?

时间:2009-10-09 02:50:30

标签: oop events dependency-injection

向上或向下?

我是一个非常有视觉的人。我认为我的应用程序是一个层次结构,其中顶部是根,底部是叶子。

我也理解,在DI系统中,容器不知道它们所包含的对象的职责/功能。相反,包含的对象知道它们的上下文,因为注入了上下文(依赖项)。

UP: (非DI方式?)
我的活动应该从我的层次结构的底部发送,并向上向他们的父母冒泡吗?例如。我的GUI中的一个按钮调度CLICKED事件,该事件由监听容器捕获,该容器通过执行适当的操作来响应。

DOWN: (DI方式?)
我的活动应该由其子级听取的父级从我的层次结构的顶部发送吗?例如。 - ...好的,我很难想出来。我正在考虑调解包含对象事件的Mediator。

'Up'对我来说似乎很自然,但由于DI有一个容器没有意识到它包含的对象的行为,我不想回应他们的事件。

编辑(澄清):

我意识到让系统的几乎任何部分听一个事件是可能的,但我想了解DI参与者之间的基本关系,所以我可以正确地构建它们 。我假设人们通常不会分散关于他们程序的事件而不考虑结构关系,依赖性等。

我的问题源于DI系统中的责任放置 - 注入对象负责对注入器进行调用,并且注入器的责任是为其依赖对象提供服务(这反转了非DI范例 - 因此同义词比如“控制倒置”和“依赖倒置”。这似乎是DI的一个非常重要的基本组成部分 - 责任转移。我考虑调用一个对象的函数或者监听它的事件,以及另一个对象的依赖的例子。当一个对象基于另一个对象定义它自己的行为时,我称之为依赖,因为一个对象知道另一个对象并且知道另一个对象的作用。它已在另一个对象的上下文中定义自己。据我所知,DI的设置使得注入的物体依赖于喷射器,因此注入物体的责任应该是了解喷射器的所有信息。并且它不应该是注射器负责了解注入的物体。因此,对于注入CONTAINED注入对象上的事件的注入器,在我看来就像错误的责任,因为这意味着它知道它的内容。

请告诉我这是否以及如何出错。

6 个答案:

答案 0 :(得分:3)

依赖关系注入和观察者模式中的角色分配是正交问题。一个对象可以扮演观察者的角色,也可以观察它,同时可以是作曲对象,组合对象,两者,或两者兼而有之。

考虑一个按钮由控件组成的典型示例。单击该按钮时,它会引发一个Clicked事件,该事件由包含控件响应。在这种情况下,观察对象正在组成观察对象。

现在考虑一个组成许多控件的屏幕。屏幕可能会引发Closing事件,允许组合控件在整个屏幕关闭之前执行自己的清理工作。在这种情况下,观察对象组成了观察者。

现在考虑一个组成按钮和标签的屏幕。单击该按钮时,将调用标签的Clear()方法。在这种情况下,观察者和观察者都不会组成另一个,但两者都是由屏幕对象组成的。

现在考虑一个屏幕,它引发一个它自己订阅的Closing事件(可能确保自己成为已注册的最终事件处理程序)。当它引发Closing事件时,允许任何观察者首先执行他们可能需要的任何操作,然后处理它自己的事件。在这种情况下,观察者就是观察者。

依赖注入涉及对象如何获取其依赖关系。注入到给定对象中的依赖项可以包含对象想要订阅的事件,或者依赖项可以订阅它正被注入的对象。两个对象在注入另一个对象后如何交互并不与依赖注入有任何关系。

修改

关于你的澄清部分,我相信我理解你的混淆的根源。传统上,对象创建自己的依赖项。依赖注入通过移动在对象之外获取依赖关系的知识来反转获得这些依赖关系的责任。但是,依赖注入不会反转依赖关系。您可能会将依赖注入与Dependency Inversion Principle混淆。依赖性反转原则确实反转了“高级”和“低级”对象之间的依赖关系,但依赖注入仅涉及如何向给定对象提供依赖性。因此,依赖注入的使用不会改变对象通常彼此交互的方式。如果在使用依赖注入对象B之前订阅了由对象A引发的事件(反之亦然),则引入依赖注入不会改变这一点。

答案 1 :(得分:1)

根据我的经验,事件将从较低的水平开始并上升,因此,当轮胎注入汽车级别时,您的轮胎会撞到一个坑洼,这将使汽车振动。

但是,您需要确保每个部分都能够处理事件。

如果汽车行驶得更快,轮胎会旋转得更快,但这不是因为事件,而是由于调用轮胎上的功能使其达到一定的速度。

我看到它正在上升,但你没有说明你是如何确定方向的。

答案 2 :(得分:1)

使用Observer Pattern作为模板,其中“parent”是调度事件的对象,“children”是等待/观察事件然后对事件进行操作的已注册侦听器。所以无论是自上而下,左右,无论你如何概念化它的原理都是一样的。

编辑:请查看Observer

视觉说明

答案 3 :(得分:1)

我说自下而上是要走的路。您可能会追求的是chain of responsibility种模式。事件从“叶子”开始。叶子要么处理它,要么将层次结构传递给父对象。叶子的父对象要么处理它,要么在层次结构中向上传递它等等。

我不认为它违反任何DI原则。但是,层次结构中的所有对象都必须实现与此类似的接口:

interface IEventHandler {
    void setNextHandler(IEventHandler nextHandler);
    void handleEvent(Event e);
}

答案 4 :(得分:0)

您是否了解消息总线架构,例如:事件和要求?

在高度并发系统中,低层正在处理诸如I / O或鼠标点击等可能是时间可用的或者操作可能被阻止的事物,例如,磁盘I / O或网络消息Tx / Rx;而高层总是处理更快的操作,也就是逻辑计算,因为高层不会涉及任何I / O等。 在这样的系统中,事件是一个通知,它通知高层发生了某些事情。例如,数据包已到达,或者已将字符串写入磁盘。一旦高层获得通知,他们将继续从事件的缓冲区中获取数据并解析事件发送的数据包。如上所述,提取和解析是纯逻辑计算并且非常快。完成后,他们可以向低层发送请求(例如,发送ACK分组)。从上到下的请求都是非阻塞的,也非常快。低层将处理请求并执行“实际发送”,即I / O操作。 高层和低层使用队列设施等进行通信。

所以在这样的系统中,你会同意事件应该从底部向上发展。

向上或向下,取决于您选择的模型。

另请参阅http://code.google.com/p/effonetmsg/downloads/list的“EffoNetMsg.pdf”中描述的高度并发模型。

答案 5 :(得分:0)

如何以类似于WPF绑定的方式传递事件?