我注意到,我的依赖注入,观察者图案重码(利用番石榴的EventBus )通常是显著难度比我写过去没有这些功能的代码进行调试。 特别是当试图确定何时以及为什么观察者代码被调用。
马丁Oderski和朋友写了一篇长篇论文具有特别诱人的标题, “弃用观察者模式” ,我还没有作出读它的时候。
我想知道什么是错与观察者模式和这么多的(建议或其他方式)的替代领导这样聪明的人写的文章好。
作为一个开始,我确实发现论文中的一个(娱乐)的批判这里 。
我注意到,我的依赖注入,观察者图案重码(利用番石榴的EventBus )通常是显著难度比我写过去没有这些功能的代码进行调试。 特别是当试图确定何时以及为什么观察者代码被调用。
马丁Oderski和朋友写了一篇长篇论文具有特别诱人的标题, “弃用观察者模式” ,我还没有作出读它的时候。
我想知道什么是错与观察者模式和这么多的(建议或其他方式)的替代领导这样聪明的人写的文章好。
作为一个开始,我确实发现论文中的一个(娱乐)的批判这里 。
直接引用的文件 :
为了说明观察者模式的精确的问题,我们从一个简单的和无处不在的例如:鼠标拖动。 下面的例子在拖动操作期间跟踪鼠标的移动Path
对象,并将其显示在屏幕上。 为了简单起见,我们使用Scala的闭包为观察员。
var path: Path = null
val moveObserver = { (event: MouseEvent) =>
path.lineTo(event.position)
draw(path)
}
control.addMouseDownObserver { event =>
path = new Path(event.position)
control.addMouseMoveObserver(moveObserver)
}
control.addMouseUpObserver { event =>
control.removeMouseMoveObserver(moveObserver)
path.close()
draw(path)
}
上面的例子中,当我们将认为如在所限定的观察者模式[25]一般而言,违反了重要的软件工程原理令人印象深刻的阵容:
副作用观察员促进副作用。 由于观察者是无状态的,我们往往需要几个人来模拟状态机的拖例子。 我们必须拯救它是所有参与的观察员访问,如变量中的状态path
之上。
封装作为状态变量path
逸出的观察员的范围内,观察者模式断裂包封。
可组合多个观察者形成以单一关注(或多个,见下点)处理对象的松散集合。 由于多个观察员在不同的点安装在不同的时间,我们不能,例如,易处置干脆它们。
的关注点分离上述观察员不仅跟踪鼠标路径,而且也调用一个绘制命令,或更一般地,包括在相同的代码位置的两个不同的关注。 通常优选以分离构成路径并显示它,例如,如在模型 - 视图 - 控制器(MVC)[30]图案的顾虑。
Scalablity我们可以通过创建路径一类本身将事件发布时的路径变化实现在我们的例子关注点分离。 不幸的是,在观察者模式的数据一致性无法保证。 让我们假设,我们将创建另一个事件发布对象,它依赖于我们原来的路径,例如改变,表示我们的道路的边界矩形。 还要考虑观察者听路径和其边界方面的变化,以绘制框架路径。 这名观察员将需要手动确定是否边界已经更新,如果没有,推迟绘图操作。 否则,用户可以观察到有错误的大小(毛刺)在屏幕上的框架。
均匀性产生不同的方法来安装不同的观察者降低代码的一致性。
抽象有抽象的例子中低水平。 它依赖于一个控制类,它提供了比安装鼠标事件观察家只是具体方法更多的重量级的接口上。 因此,我们不能抽象的过度精确的事件源。 例如,我们可以让用户通过按ESC键中止拖拽操作或使用不同的指针设备,如触摸屏或图形输入板。
资源管理观察者的生活时需要由客户进行管理。 由于性能原因,我们只想要拖动操作过程中,观察鼠标移动事件。 因此,我们需要明确安装和卸载鼠标移动观察者和我们需要记住的安装点(对照上图)。
语义距离最终,例如很难理解,因为控制流反转导致过多的样板代码,增加了程序员的意图和实际的代码之间的语义距离。
[25] E.伽马,R.头盔,R. Johnson和J. Vlissides。 设计模式:可重用面向对象软件元素。 Addison-Wesley出版社朗文出版公司,公司,波士顿,MA,USA,1995 ISBN 0-201-63361-2。
我相信Observer模式有标准的缺点来与去耦的事情。 该主题会从观察脱钩,但你不能仅仅看它的源代码,并找出谁观察它。 硬编码的依赖性通常更易于阅读和思考,但他们是难以修改和重用。 这是一个权衡。
至于纸,它没有解决Observer模式本身,而是它的一个特殊用法。 特别地: - 可见每单个对象的多个无状态的观察对象。 这有独立观察家需要相互(同步的明显缺点“由于观察者是无状态的,我们往往需要几个人来模拟状态机在拖动的例子。我们必须拯救它是可访问状态所有涉及的观察员如在上面的可变路径“)。
上述缺陷是特定于这种用法,不向观察者模式本身。 你还可创建一个实现所有单(有状态!)观测对象OnThis
, OnThat
, OnWhatever
方法,摆脱在许多无状态的对象模拟状态机的问题。
我将简短的,因为我是新来的主题(并没有阅读具体条款还没有)。
观察者模式直观错误的:被观察对象知道谁是观察(主题为<> - 观察员)。 这是对现实生活中的(基于事件的场景)。 如果我尖叫,我不知道是谁在听; 若闪电,撒在地板上......闪电不知道,有一个地板,直到它击中! 只有观察员知道他们可以观察到的东西。
当这样的事情发生,然后使用软件将一个烂摊子 - 因为构成对我们的thinking-方式。 这是因为如果和对象知道其他对象可以调用他的方法。
IMO如“环境”的层是一个负责采取事件和通知受到影响的。 (OR混合的事件,该事件的发生)
事件源(主题)生成事件的环境。 环境提供事件的观察。 观察者可以注册到的那种事件的影响他或它在实际环境中定义。 这两种可能性道理(但我想简短)。
在我的理解Observer模式拼环境和主题。
PS。 讨厌放在段落天马行空的想法! :P