你站在桥上看风景,看风景的人在楼上看你。明月装饰了你的窗子,你装饰了别人的梦。
我们只说前面2句。
第一句:当你站在桥上看风景的时候,眼前的风景是你观察的对象,也可以说风景是被你观察的对象。
第二句:当楼上的人出现时,看风景的你,却又变成了被看的风景,你是楼上人的观察的对象,也可以说你是被楼上人观察的对象。
呵呵,不知道我们这么理解,如果卞老还在的话,会不会吐血啊,没办法模式本身就是形而上学的东西。
螳螂捕蝉黄雀在后
螳螂正要捉蝉,却不知道黄雀在它后面正要吃它。这句成语常指人目光短浅,只顾眼前的利益,没有远见。
但是在我们开发上很多时候,却要做到“螳螂捕蝉黄雀在后”。
呵呵,上面说了那么多废话,就是想让大家有个形的概念,今天说下eternal框架里的观察模式。模式来源形,什么是形,是形式表现,java的代码片段或一些组合就是形,某种的形的反复出现时,我们就可以把它独立出来一种解决问题的模式。
观察者模式
Observer模式定义对象间的一对多的依赖关系,当一个对象(被观察者)的状态发生改变时, 所有依赖于它的对象(观察者)都得到通知并被自动更新。
有了前面的说明,在理解观察者模式就很容易啦,他为我们提供了一种解决耦合的一种方式或者响应事件处理的一种方法。
那么如果实现它呢?前面我说的2个例子,有一点是不对的,被观察者有些时候不是不知道观察者的存在,相反他可能持有所有的观察者实例,但这不是绝对,不持有通过其他的机制使之发生关系,如广播和监听等,套路是固定的,但是怎么发挥就的看情况啦。
我们通过具体的java代码,看下如何实现它,我们以“螳螂捕蝉黄雀在后”的例子,这个例子和实际还是有些出入的,在代码里蝉是知道螳螂的,螳螂也知道黄雀。(希望不会误导大家)。
Cicada.java蝉,Mantis.java螳螂,Vertin.java黄雀,Test.java螳螂捕蝉黄雀在后
package cn.design.observermode; import java.util.Observable; //蝉 public class Cicada extends Observable { private int distance; public void move(){ for(int i=100;i>=10;i--){ this.distance = i; System.out.println("蝉,距离螳螂"+distance+"cm"); this.setChanged(); this.notifyObservers(this.distance); } } }
package cn.design.observermode; import java.util.Observable; import java.util.Observer; import cn.design.observermode.Cicada; //螳螂 public class Mantis extends Observable implements Observer { @Override public void update(Observable o, Object arg) { if(o instanceof Cicada){ this.attack(Integer.parseInt(arg.toString())); }else{ //同时窥测的其他猎物 } } private void attack(int distance){ if(distance>50){ System.out.println("螳螂:猎物太远 蛰伏"); }else if(distance>10 && distance<=50){ System.out.println("螳螂:猎物靠近 伺机而动"); }else{ System.out.println("螳螂:猎物进入攻击范围 猎杀"); this.setChanged(); this.notifyObservers(distance); } } }
package cn.design.observermode; import java.util.Observable; import java.util.Observer; //黄雀 public class Vertin implements Observer { @Override public void update(Observable o, Object arg) { if(o instanceof Mantis){ this.attack(); }else{ //同时窥测的其他猎物 } } private void attack(){ System.out.println("黄雀:螳螂已经将蝉捕杀,立即捕杀螳螂"); } }
package cn.design.observermode; public class Test { //螳螂捕蝉,黄雀在后 的 故事,观察者模式 public static void main(String[] args) { Cicada cicada = new Cicada(); Mantis mantis = new Mantis(); Vertin vertin = new Vertin(); cicada.addObserver(mantis); mantis.addObserver(vertin); cicada.move(); } }
我们分析一下上面的代码,在Test中cicada.addObserver(mantis);我们看到蝉持有螳螂的实例(蝉喊螳螂,“你来吃我啊”),同样螳螂持有黄雀的实例,一切的开始于蝉的移动,在move中,我们看到蝉没动一下,都通知螳螂,螳螂判断最佳时机杀死蝉,同时通知黄雀,我的死期到啦。
上面是Observable,Observer都是java api实现的好的,我们直接继承就好啦。
上面跑题啦,java api实现的东西,对于我这苦海的小修士来说,简直是大帝般的存在,我只能仰望啊,不过仰望大帝还是有些心得的。下面我们用javascript模拟一下java的api实现下,观察者模式。
function XObservable(){ var observers;//观察者列表 } XObservable.prototype.addObserver = function (observer) { if (this.observers.indexOf(observer) < 0) { this.observers.add(observer); } }; XObservable.prototype.removeObserver = function (observer) { this.observers.remove(observer); }; XObservable.prototype.removeObservers = function () { this.observers.clear(); }; XObservable.prototype.notifyObservers = function (arg) { for (var i = 0; i < this.observers.size(); i++) { this.observers.get(i).update(arg); } };
var observable = new XObservable(); observable.addObserver(new 观察者1()); observable.addObserver(new 观者者2());
观察者1.prototype.update = function (arg){ //实现自己的功能 }