• [设计模式]观察者模式


    我们常常会做到这样的一种效果,例如A被点击之后,要求B和C会执行特定的行为。
    画图什么的很烦,下面举个简单的例子:

    var DomA = document.getElementById("divA");
    var DomB = document.getElementById("divB");
    var DomC = document.getElementById("divC");

    DomB.action = function(){
    alert("I'm DomB, I know DomA be clicked");
    }
    DomC.action = function(){
    alert("I'm DomC, I know DomA be clicked")
    }

    DomA.onclick = function(){
    DomB.action();
    DomC.action();
    }

    以上就是观察者模式的简单原理演示,是不是很简单?当然只是流程式的表达意思啦,有点事件监听的味道。看着像是DomA去主动通知DomB和DomC。
    OK,清楚简单的原理之后,以下我们就用面向对象的方法来写一个关于观察者模式的片断。

    首先,我们要清楚需要些什么?
    1、需要一个用来保存观察者的队列,可以用一个数组来保存。
    2、需要一个可以方便操作以上观察者队列的类,这样我们就可以方法添加和删除观察者了。

    //这是一个操作观察者的类
    function ObList(){
    this.list = [];
    }

    //我习惯把方法写到函数的原型链上,因为这样可以节省内存开支。
    //
    统计观察者的个数的方法
    ObList.prototype.Count = function(){
    return this.list.length;
    }

    //增加观察者对象的方法
    ObList.prototype.Add = function(object){
    if(object){
    return this.list.push(object);
    }
    }

    //获取指定的观察者对象的方法
    ObList.prototype.Get = function(index){
    //判断index是否在数组长度范围之内
    if(index > -1 && index<this.list.length){
    return this.list[index];
    }
    }

    当然,上面只写了三个简单的方法,只是为了演示本例,可以按自己需要添加更多的方法。

    好了,接着,我们需要定义一个Subject类,这个类的目的在于处理被观察者与观察者之间的关系和操作。大概需要以下功能:
    1、添加观察者对象
    2、获取观察者对象
    3、通知观察者
    前两者就可以引用刚才的ObList类的实例:

    //这是一个主题类
    function Subject(){
    this.observers = new ObList();
    }

    //通知观察者的方法
    Subject.prototype.Notify = function(context){
    if(context){
    var ob_count = this.observers.Count();
    for(var i = 0; i < ob_count; i++){
    this.observers.Get(i).Action(context);
    }
    }
    }

    //增加观察者的方法
    Subject.prototype.AddObserver = function(observer){
    if(observer){
    this.observers.Add(observer);
    }
    }

    好,“前戏”已经准备好了,我们还未至于急于进入,呵呵,有没发觉少了些什么?
    我们这些“前戏”不仅是给某个对象而准备的,也不是给永远仅属于某个对象的。他可以用到A,B,C...对象。
    那么,这些方法我们很有可能重用。以下,我们准备一个继承函数,可以把这些方法添加到任意对象上。以后用起来就随心所欲啦。

    //这是一个非常经典又普通的继承函数,浅拷贝
    function Inherits(base,extension){
    for(var property in base){
    extention[property] = base[property];
    }
    //这里省略了异常判断
    }


    以下开始运用我们前面的代码:

      var d = window.document;
    var DomA = d.getElementById("divA");
    var DomB = d.getElementById("divB");
    var DomC = d.getElementById("divC");

    //让DomA对象继承Subject方法
    Inherits(DomA,new Subject());

    //设置DomB对象的action方法
    DomB.Action = function(msg){
    this.innerHTML = "I'm DomB, I get a message:" + msg;
    }

    //同样地,设置DomC对象的action方法
    DomC.Action = function(msg){
    this.innerHTML = "I'm DomC, I get a message:" + msg;
    }

    //把DomB和DomC添加为DomA的观察者
    DomA.AddObserver(DomB);
    DomA.AddObserver(DomC);

    //让DomA对象通过onclick事件去触发他的Notify方法
    DomA.onclick = function(){
    this.Notify("DomA be clicked");
    }

    整个例子演示完毕,其实就是把观察者放到一个数组里,然后被观察者通过事件(onclick)触发(Notify)去遍历观察者(observer)的指定方法(action)。



  • 相关阅读:
    洛谷 P4707 重返现世
    多项式总结&多项式板子
    线性常系数齐次递推
    洛谷 P2791 幼儿园篮球题
    CF Gym 102028G Shortest Paths on Random Forests
    洛谷 P4705 玩游戏
    [NOI2018]冒泡排序
    PKUSC2019 改题记录
    PKUSC2019 没约记
    Codeforces Round #557 题解【更完了】
  • 原文地址:https://www.cnblogs.com/zzbo/p/2348913.html
Copyright © 2020-2023  润新知