在Smalltalk/VisualWorks中实现观察者模式

3

我初次接触编程模式,花了几个小时搜寻Smalltalk实现观察者模式的样例,但都没有成功。 如果有人能够提供一个具体的关于在Smalltalk中实现此模式的样例,那就万分感谢。


感谢大家的回答,对我很有帮助。 - SolidSnake87
3个回答

12

在Smalltalk中,观察者模式的标准实现是#changed/#update机制。

它的实现方式如下:

subject addDependent: anObserver.

subject changed.

然后anObserver收到发送的#update
MyObservingObject>>update
  "I got called in a #changed chain"
  super update.
  self doUpdatingStuff

你可以使用 #changed:#update:(注意冒号)来获得更精细的控制:
subject addDependent: anObserver.
subject changed: subject.

并且

MyObservingObject>>update: anObject
  "I got called in a #changed: chain"
  super update: anObject.
  self doUpdatingStuffWith: anObject

然而,通常会使用符号来表示发生的变化:
subject addDependent: anObserver.
subject changed: #myNumbers.

并且

MyObservingObject>>update: anObject
  "I got called in a #changed: chain"
  anObject == #myNumbers ifTrue: [
    self doUpdatingStuffForNumbers.
    ^ self "inhibits the super"].
  super update: anObject.

当您查看SqueakPharo时,您将至少找到另外三个观察者实现:
  • Morphic的事件处理(请参见Morph>>#on:send:to:
  • 类似的、更通用的事件处理机制,请参见Object>>#when:send:to:Object>>#triggerEvent:
  • Announcements框架,封装了主题和观察者之间的消息。
您可以在Signals项目中找到这些内容的比较,该项目是受Qt启发的另一个实现。

这个 changed 消息是默认调用的吗?例如,当向集合中添加/删除某些内容时,可以假设其依赖项将被更新吗? - Mr Tsjolder
不,你必须自己完成这个任务。请参见 #changed#changed: 的发送者。 - Tobias
我该如何找到 #changed#changed 的发送者?为了获得这种行为,最佳实践是什么?更改现有类的源代码(例如某些 Collection 实现)或创建子类以添加该行为? - Mr Tsjolder
在Squeak和Pharo中查找发送者可以使用Alt-n或MethodFinder / Finder。集合通常不会自己发送#changed。此外,您通常不会对集合进行子类化。一个好的方法是创建您的领域模型类,该类保存集合(组合)并在添加到其集合时发送#changed - Tobias

5
最简单的方式可能是这样的:
在观察者类中:
observable: anObject
    observable := anObject.

observable
    ^ observable.

notify
    "do something here e.g.:"
    Transcript show: "Some things changed in ", observable asString.

在 Observable 中:
initialize
    observers := OrderedCollection new.

addObserver: anObserver
    observers add: anObserver.

removeObserver: anObserver
    observers remove: anObserver.

notifyObservers
    observers do: [ :each | each notify ].

但我建议您在有关通知框架的章节中更多地了解这个想法。


2
此外,看看 Announcements 框架。它比发送符号更加面向对象。 祝好

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