电影《模仿游戏》中,讲述了我们的计算机科学之父图灵
通过制造背后那个大机器,来协助盟军破译德国密码系统“英格玛”
,从而扭转二战战局的经历。
如果没图灵用这大机器来破译情报,知道敌军动向,估计整个二战战局可能都被改写!
尽管历史没假设,事实就是事实。
今天我们要说的观察者就是这样的功效,他监视着被观察者,一有什么风吹草动就打报告。
有了上面这个故事背景,我们该来怎么模拟这个过程呢?
先来看下我们图灵哥做的
public class Turing {
public static void main(String[] args) {
Germany germany = new Germany();
germany.addObserver(new MachineObserver());
germany.operationOverlord();
}
}
图灵做的就是给我们的德国加多一个机器观察者,当德国有什么行动时候,就可以知道
我们来看下我们的德国。
public class Germany implements Observable {
private List observableList = new ArrayList<>();
public void operationOverlord() {
notifyObservers("operationOverlord");
}
@Override
public void addObserver(Observer observer) {
observableList.add(observer);
}
@Override
public void deleteObserver(Observer observer) {
observableList.remove(observer);
}
@Override
public void notifyObservers(String action) {
for (Observer observer : observableList) {
observer.updateMsg(action);
}
}
}
在他的执行行动中operationOverlord()
穿插了我们的间谍,监视到有新的行动时候,就通知
notifyObservers("operationOverlord")
我们消息。
同时对于我们的间谍机构Observable
,我们有制定三个基本的功能,让间谍悄悄的潜入addObserver
,悄悄的消失deleteObserver
,发送情报notifyObservers
。
public interface Observable {
public void addObserver(Observer observer);
public void deleteObserver(Observer observer);
public void notifyObservers(String context);
}
这个我们已经安装在我们的德国上了。
接着我们看下我们的间谍,基本就是更新消息。
public interface Observer {
public void updateMsg(String newAction);
}
我们生成了一个机器间谍。
public class MachineObserver implements Observer {
@Override
public void updateMsg(String newAction) {
System.out.println("germany's is trying to " + newAction);
}
}
好了,这样我们的整个观察者模型就基本搭建好了。
现在,我们可以运行一下了,看下我们的机器间谍在我们的图灵指挥下,打印出了内容
germany's is trying to operationOverlord
德国居然要去搞霸王行动….这是乱入?
在简单的说了这个监视过程,写完了我们的观察者模式。但上面的略显负责,因为我们的Java已经给我们做好了很多的内容,我们不需要自己写Observer
和Observable
,因此我们可以缩短一点,变成下面这样子的
我們的德國可以用java.util.Observable
的“間諜機構”。
import java.util.Observable;
public class Germany extends Observable {
public void operationOverlord() {
setChanged();
notifyObservers("operationOverlord");
}
}
而對於我們的機器間諜用的是java.util.Observer
public class MachineObserver implements Observer {
@Override
public void update(Observable observable, Object data) {
System.out.println("germany's is trying to " + data.toString());
}
}
這樣我們的代碼看起來是不是簡潔了一些?
最後看下我們的图灵,内容没变
public class Turing {
public static void main(String[] args) {
Germany germany = new Germany();
germany.addObserver(new MachineObserver());
germany.operationOverlord();
}
}
好了,这样整个我们就写得很小啦
这里用的是Java包的内容,不过如果你要自己动手实现也是可以的,并没有区别,只是不建议造多轮子而已。
对于观察者,有一个变体叫发布/订阅模型
,在安卓开发中,有EventBus和Otto这两个库就是这样的思路。
不过对于观察者,有一个要注意的就是避免广播链的建立,这个一环套一环,和我们的死锁一样的可怕的。
另外我们的观察者尽量不要做过多耗时的操作,避免影响后面的观察者接收消息,因为我们的通知是顺序执行的,如果过于耗时,建议把观察者的具体操作改成异步的,如果你的实际业务逻辑可以接受同步的话,那就无所谓啦。