设计模式——观察者模式

设计模式——观察者模式

在上一篇文章中已经介绍了设计模式的一些基本原则,现在通过提出一个新问题引入我们即将介绍的观察者模式。还是以Car类作为我们介绍的例子,我们现在希望让Car拥有DashBoard(仪表盘),并且让仪表盘显示的数据随着Car的数据改变实时变化。在没学习Swift之前,如果让我用Java实现,我会在Car类中对Car的属性添加get方法,并在DashBoard类中添加更新仪表盘显示数据的方法,每次调用方法时动态的get需要的Car类的数据。

这么做犯下了一个原则性的错误,在设计模式入门中提到,不要针对具体实现编程,如果我们使用这个方法对仪表盘数据进行更新,我们必须在Car类中针对特定的仪表盘进行更新。但其实这么做距离我们实现观察者模式,只有一步之遥了,我们需要把指定的仪表盘,替换成多个观察者对象,而数据本身不用关心观察者对象的数量和具体实现,只需要在变化时调用观察者对象的方法即可,而这么做还有一个好处,我们可以动态的添加或者删除观察者,而不会影响数据运行的结果。像我们之前那样实现,DashBoard与Car的关联就被从代码层面写死了,我们如果想添加新的DashBoard必须修改代码,这就是两个对象之间耦合过深,所以引入下一条设计原则:

为了交互对象之间的松耦合设计而努力。

松耦合,又叫抽象耦合,的意思是两个对象可以进行交互,但不清楚彼此的细节,在我看来这就像一个沙漏结构,沙漏的两侧只通过很小的一个孔与另一侧交互,两侧彼此不知道对方还剩多少沙、容器的形状等等具体的细节,它们关心的仅仅是当前通过沙漏的数据。观察者模式的本质就是让观察者与被观察者松耦合。

被观察者不需要知道观察者将要执行的操作,观察者也不需要知道被观察者数据改变的原因,它只关心被观察者的数据是否发生变化,如果要变化观察者的话,只需要动态的注册与删除观察者就能实现。

最后使用观察者模式改造我们的Car类后Car类的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Car implements Observable {
private double speed = 0;
private ArrayList<DashBoard> observers = new ArrayList<>();
public void setSpeed(double newSpeed) {
this.speed = newSpeed;
notifyObservers();
}

@Override
public void registerObserver(DashBoard newObserver) {
observers.add(newObserver);
}

@Override
public void removeObserver(DashBoard observer) {
observers.remove(observer);
}

@Override
public void notifyObservers() {
for (DashBoard observer : observers) {
observer.update(speed);
}
}
}

UML类图

Observable为接口,供可观察者实现,用于对观察者进行操作,包括通知观察者,注册新观察者,删除某特定观察者。改造后我们在Car类中就不会再看见具体实现的某个DashBoard类了。其实在Java中已经有自带的Observable和Observer,但是Java自带的实现与上文所说的略有区别,在Java中Observable是一个父类而非接口,我们通过继承这个父类实现可被观察的类,但我个人认为,这么做并不方便,在Java中只能继承一个类,但是可以实现多个接口,使用接口实现这个目的会更灵活。

Swift中的 didSetwillSet 与Observer Pattern

didSet和willSet在Swift是一个很实用的语法,提供了当变量被改变时进行操作的机会,但是这只是观察者模式的一部分,我们在上文提到,观察者模式的本质是实现观察者与被观察者的松耦合,观察者模式不是一种特定的语法,而是一种程序设计的思想。didSet仅仅只是为我们观察属性的变化提供了便利,并没有主动实现松耦合,如果我们依然将观察者写死在被观察者类中,就算使用了didSet,也不叫观察者模式。

我们思考一个问题,当两个对象互相为彼此的观察者,会发生什么事情?这样的两个对象之间的关系叫做循环依赖,当它们的值发生改变时会导致循环调用,进而引起程序崩溃,这是观察者模式的小小漏洞,我们需要在编程开发中格外注意。


参考:

Design Patterns in Swift: Observer Pattern——Sam Stone


设计模式——观察者模式
https://wenchanyuan.com/design_pattern_observer_pattern/
作者
蟾圆
发布于
2019年12月1日
许可协议