【js设计模式笔记---观察者模式】

    xiaoxiao2023-03-24  2

    观察者模式

    又称发布—订阅者(publisher-subscriber模式),这是一种多对多的关系,需要一种高级的抽象策略,以便订阅者能够彼此独立地发生改变,而发行方能够接受任何有消费意向的订阅者。

    模式的实践

    在javascript中有很多种方法可能实现发布—订阅模式。在展示那些示例之前,我们先确保各种角色的扮演者(对象)及其行为(方法)都已就绪。

    1.   订阅者:可以订阅和退订。它们还要接收。他们可以由人投送和自己收取之间进行选择。

    2.   发布者:负责投送。他们可以送出和由人取之间进行选择。

    下而一个展示发布和订阅者之间互动的高级示例。它是Sells方法的一个示范。这种技术类似于测试驱动开发TDD,不过它要求先写实现代码,就像API已经写好了一样。为了让这些代码成为可运转的真正实现,程序员需要完成各种该做的工作,

     

    var Publisher =new Observable;

    var Subscriber =function(news){

              //news delivered directly to my frontporch

    }

    Publisher.subscribCustomer(Subscriber);

    Publisher.deliver(“extre,extre,read all about it ”);

    Publisher.unSubscribeCustomer(Subscriber);

    在这个模型中,可以看出发布者处于明显的主导地位。它们负责登记其顾客,而且有权停止为其投送。最后,新的报纸出版后它们会将其投送给顾客。上面的代码创建了一个新的可观察对象(observable)对象。它有三个实例方法:

    subscribeCustomer/unSubscribeCustomer和deliver。

    subscribeCustomer方法以一个代表访问都的回调函数为参数。

    deliver方法在调用过程中将通过这些回调函数把数据发送给每一个订阅者。

    /*NewspaperVendors stepup as new Publisher objects*/

    var NewYorkTimes =new Publisher;

    var AustinHerald =new Publisher;

    var sfChronicle =new Publisher;

     

    /*People who liketo read (Subscribers) */

    var Joe =function(from){

        console.log(“Delivery from ”+from+” to Joe”);

    }

    var Quadaras =function(from){

        console.log(“Delivery from ”+from+” to Quadaras”);

    }

    var Lindsay =function(from){

        console.log(“Delivery from ”+from+” to Lindsay”);

    }

    Joe.subscribe(NewYorkTimes);

    Joe.subscribe(sfChronicle)

     

    Lindsay.subscribe(NewYorkTimes)

    Lindsay.subscribe(sfChronicle)

    Lindsay.subscribe(AustinHerald)

     

    Quadaras.subscribe(AustinHerald)

    Quadaras.subscribe(sfChronicle)

     

    NewYorkTimes.deliver(“Hereis your paper! Direct from the Big apple”);

    AustinHerald.deliver(“News”).deliver(“Reviews”).deliver(“Coupons”);

    sfChronicle.deliver(“Theweather is still chilly”).deliver(“Hi Mom! I\’m writing a book.”);;

    这个例子中,发布者的创建方式和订阅者的接收数据 的方式没多少改变,但拥有订阅和退订的一方变成了订阅者。当然,负责发送数据的还是发布者一方。

    构建观察者API

    在明确了观察者模式中的核心成员之后,现在可以着手构建其API了。首先,我们需要一个发布者的构造函数,它为该类实例定义了一个类型为数组的属性,用来保存订阅者的引用:

    functionPublisher(){

        this.subscribers = [];

    }

    投送方法

    所有Publisher实例都应该能够投送数据。只要把deliver方法添加到Publisher的prototype中,它就能够被所有Publisher对象共享:

    Publisher.prototype.deliver= function(data){

           this.suscribers.forEach(function(fn){

                   fn(data);

            });

            return this; //chain call

    }

    订阅方法

    下一步是给予订阅者订阅的能力:

    Function.prototype.subscribe = function(publisher){

    var that = this;

    var alreadyExists = publisher.subscribers.some(functon(el){returnel===that;});

    if(!alreadyExists){

           publisher.subscribers.push(this);

    }

    return this;

    }

    退订方法

    unsubscribe方法可供订阅者用来停止对指定发布者的观察:

    Function.prototype.unsubscribe= function(publisher){

         var that = this;

         publisher.subscribers =publisher.subscribers.filter(function(el){return el!==that});

         return this;

    }

     

    有些订阅者在监听到某种一次性的事件之后会回调阶段立即退订事件。其做法大致如下:

    var publisherObject= new Publisher;

    var observerObject= function(data){

               console.log(data);

               argument.callee.unsubscribe(publisherObject);

    }

    observerObject.subscribe(publisherObject);

     

    现实生活中的观察者

    在现实世界中,观察者模式对于那种由许多javascript程序员合作开发的大型程序特别有用。它可以提供API的灵活性,使并行开发的多个实现能够彼此独立地进行修改。作为开发人员,你可以对自己的应用程序中什么是“令人感兴趣的时刻”做出决定。你所能监听的不再只有clikc、load、blur和mouseover等浏览器事件。在富用户界面应用程序中,drag、drop、moved、complete和tabSwitch(标签切换)都是令人感兴趣的事件。它们都是在普通浏览器事件的基础上抽象出来的可观察事件,可由发布者对象向其监听者广播。

    示例动画

    动画是在应用程序中实现可观察对象的一个很好的起点。眨眼间你就能想出至少3个可观察到的时刻:开始、结束和进行中。在本例中,我们将分别称之为onStart/onComplete和onTween。下面的代码演示了用前面编写的Publisher工具实现这些事件的过程。

    //Publisher API

    var Animation =function(o){

    this.onStart = new Publisher,

    this.onComplete = new Publisher,

    this.onTween = new Publisher;

    }

    Animation.mothod(‘fly’,function(){

               this.onStart.deliver();

               for(..){//loop through frames

                   //deliver frame number

                    this.onTween.deliver(i);

               }

               this.onComplete.deliver();

    });

    var Superman = newAnimation({…config properties…});

    //Beginimplementing subscribers

    var putOnCape =function(i){};

    var takeOffCape =function(i){};

    putOnCape.subcribe(Superman.onStart);

    takeOffCape.subscribe(Superman.onComplete);

    //fly can becalled anywhere

    Superman.fly();

    //for instance

    addEnvet(element,”click”,function(){

       Superman.fly();

    });

    转载请注明原文地址: https://ju.6miu.com/read-1200218.html
    最新回复(0)