设计模式系列13---感知变化的观察者模型

enter image description here
电影《模仿游戏》中,讲述了我们的计算机科学之父图灵通过制造背后那个大机器,来协助盟军破译德国密码系统“英格玛”,从而扭转二战战局的经历。

如果没图灵用这大机器来破译情报,知道敌军动向,估计整个二战战局可能都被改写!
尽管历史没假设,事实就是事实。

今天我们要说的观察者就是这样的功效,他监视着被观察者,一有什么风吹草动就打报告。

代码实现

有了上面这个故事背景,我们该来怎么模拟这个过程呢?

先来看下我们图灵哥做的

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<Observer> 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已经给我们做好了很多的内容,我们不需要自己写ObserverObservable,因此我们可以缩短一点,变成下面这样子的
我們的德國可以用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();
    }
}

好了,这样整个我们就写得很小啦

类图

enter image description here
这里用的是Java包的内容,不过如果你要自己动手实现也是可以的,并没有区别,只是不建议造多轮子而已。

#后记
对于观察者,有一个变体叫发布/订阅模型,在安卓开发中,有EventBus和Otto这两个库就是这样的思路。

不过对于观察者,有一个要注意的就是避免广播链的建立,这个一环套一环,和我们的死锁一样的可怕的。
另外我们的观察者尽量不要做过多耗时的操作,避免影响后面的观察者接收消息,因为我们的通知是顺序执行的,如果过于耗时,建议把观察者的具体操作改成异步的,如果你的实际业务逻辑可以接受同步的话,那就无所谓啦。

热评文章