JavaScript设计模式系列 ---- 观察者模式

124 阅读4分钟

观察者模式简单介绍

  • 观察者模式:
    • 发布者: 信息的发布者
    • 观察者: 被观察者状态发生改变或者发布了信息,需要采取行动的对象
  • 观察者模式的优点:
观察者模式实现(基础版本) 01
  • 步骤

    • 1.提供一个发布者
    • 2.提供一个观察者
    • 3.注册观察者(建立发布者和观察者之间的联系)
    • 4.发布者发布信息
  • 目前: 1个发布者 2个观察者 1个信息

  • 思考:2个发布者

// 1. 提供一个发布者
    var rose = {
        user: [],
        addUser: function (fn){
            if(typeof fn != 'function') throw '非法操作';
            this.user.push(fn);
        },
        removeUser: function(fn){
            if(typeof fn != 'function') throw '非法操作';
            var index = this.user.indexof(fn);
            this.user.splice(index,1)
        },
        // 发布信息
        eat: function (){
            for(var i = 0 ; i< this.user.length; i++){
               this.user[i](); 
            }
        }
    };
    
// 2.提供一个观察者
    var jack = {
        jack_eat: function(){
            console.log('邀请女神吃大餐!--jack');
        }
    }
    
    var tom = {
        tom_eat : function(){
            console.log('邀请女神吃麻辣烫--tom');
        }
    }
    
// 3.注册观察者(建立发布者和观察者之间的联系)
    rose.addUser(jack.jack_eat);
    rose.addUser(tom.tom_eat);
    
// 4. 发布者发布信息
    rose.eat();
    
// 5.移除观察者
    rose.removeUser(jack.jack_eat);
    
    rose.eat()
观察者模式实现(多个发布者) 02
  • 提供一个发布者模板
  • 利用模板提供一个方法快速创建发布者
  • 目前: 2个发布者 提供一个发布者模板
  • 思考: 发布多个信息
// 1. 提供一个发布者模板
    var publisher = {
        user: {
            eat:[],
            sleep:[]
        },
        addUser: function (fn,type){
            var type = type || 'eat';
            if(typeof fn != 'function') throw '非法操作';
            this.user[type].push(fn);
        },
        removeUser: function(fn,type){
            if(typeof fn != 'function') throw '非法操作';
            var index = this.user[type].indexof(fn);
            this.user[type].splice(index,1)
        },
        // 发布信息
        eat: function (){
            for(var i = 0 ; i< this.user['eat'].length; i++){
               this.user['eat'][i](); 
            }
        },
        sleep: function (){
            for(var i = 0 ; i< this.user['sleep'].length; i++){
               this.user['sleep'][i](); 
            }
        }
    };
    
    var rose = {};
    var wml = {};
    
// 2.封装一个函数快速创建发布者
    function makePulisher(obj){
        for(var key in pushlisher){
            // 只需要拷贝实例方法
            if(pushlisher.hasOwnProperty(key) && (typeof publisher[key] == 'function')){ 
            obj[key] = pushlisher[key];
            }
        }
        // 手动添加
        obj.user = {
            eat : [],
            sleep : []
        };
    }
    
// 让rose成为发布者
    makePulisher(rose);
    makePulisher(wml);
    
    // 2.提供一个观察者
    var jack = {
        jack_eat: function(){
            console.log('邀请女神吃大餐!--jack');
        },
        jack_sleep : function(){
             console.log('wanan!--jack');
        }
    }
    
    var tom = {
        tom_eat : function(){
            console.log('邀请女神吃麻辣烫--tom');
        },
        tom_sleep : function(){
            console.log('kanxingxing--tom');
        }
    }
    
// 3.注册观察者(建立发布者和观察者之间的联系)
    rose.addUser(jack.jack_eat,'eat');
    rose.addUser(jack.jack_sleep,'sleep');
    rose.addUser(tom.tom_sleep,'sleep');
    
// 4. 发布者发布信息
    ///rose.eat(); 
    rose.sleep();
    
// 5.移除观察者
    rose.removeUser(jack.jack_sleep.'sleep');
    rose.sleep()
观察者模式实现(多个状态) 03
  • 把数组改为对象保存多个状态
// 1. 提供一个发布者模板
    var publisher = {
        user: {
            eat:[],
            sleep:[]
        },
        addUser: function (fn,type){
            var type = type || 'eat';
            if(typeof fn != 'function') throw '非法操作';
            this.user[type].push(fn);
        },
        removeUser: function(fn,type){
            if(typeof fn != 'function') throw '非法操作';
            var index = this.user[type].indexof(fn);
            this.user[type].splice(index,1)
        },
        // 发布信息
        eat: function (){
            for(var i = 0 ; i< this.user['eat'].length; i++){
               this.user['eat'][i](); 
            }
        },
        sleep: function (){
            for(var i = 0 ; i< this.user['sleep'].length; i++){
               this.user['sleep'][i](); 
            }
        }
    };
    
    var rose = {};
    var wml = {};
    
// 2.封装一个函数快速创建发布者
    function makePulisher(obj){
        for(var key in pushlisher){
            // 只需要拷贝实例方法
            if(pushlisher.hasOwnProperty(key) && (typeof publisher[key] == 'function')){ 
            obj[key] = pushlisher[key];
            }
        }
        // 手动添加
        obj.user = {
            eat : [],
            sleep : []
        };
    }
    
// 让rose成为发布者
    makePulisher(rose);
    makePulisher(wml);
    
    // 2.提供一个观察者
    var jack = {
        jack_eat: function(){
            console.log('邀请女神吃大餐!--jack');
        },
        jack_sleep : function(){
             console.log('wanan!--jack');
        }
    }
    
    var tom = {
        tom_eat : function(){
            console.log('邀请女神吃麻辣烫--tom');
        },
        tom_sleep : function(){
            console.log('kanxingxing--tom');
        }
    }
    
// 3.注册观察者(建立发布者和观察者之间的联系)
    rose.addUser(jack.jack_eat,'eat');
    rose.addUser(jack.jack_sleep,'sleep');
    rose.addUser(tom.tom_sleep,'sleep');
    
// 4. 发布者发布信息
    ///rose.eat(); 
    rose.sleep();
    
// 5.移除观察者
    rose.removeUser(jack.jack_sleep.'sleep');
    rose.sleep()
观察者模式实现(优化) 04
  • 动态添加对象user
// 1. 提供一个发布者模板
    var publisher = {
        addUser: function (fn,type){
            var type = type || 'eat';
            if(typeof fn != 'function') throw '非法操作';
            if(this.user[type] == undefined){
                this.user[type] = [];
            }
            this.user[type].push(fn);
        },
        removeUser: function(fn,type){
            if(typeof fn != 'function') throw '非法操作';
            var index = this.user[type].indexof(fn);
            this.user[type].splice(index,1)
        },
        // 发布信息
        publish : function (type){
            var type = type || 'eat'
            for(var i = 0 ; i< this.user[type].length; i++){
               this.user[type][i](); 
            }
        }
    };
    
    var rose = {
        eat: function(){
            this.publish('eat');
        },
        sleep: function(){
            this.publish('sleep')
        },
        run: function(){
            this.publish('run')
        }
    };
    var wml = {};
    
// 2.封装一个函数快速创建发布者
    function makePulisher(obj){
        for(var key in pushlisher){
            // 只需要拷贝实例方法
            if(pushlisher.hasOwnProperty(key) && (typeof publisher[key] == 'function')){ 
            obj[key] = pushlisher[key];
            }
        }
        // 手动添加
        obj.user = {};
    }
    
// 让rose成为发布者
    makePulisher(rose);
    
    // 2.提供一个观察者
    var jack = {
        jack_eat: function(){
            console.log('邀请女神吃大餐!--jack');
        },
        jack_sleep : function(){
             console.log('wanan!--jack');
        }
    }
    
    var tom = {
        tom_eat : function(){
            console.log('邀请女神吃麻辣烫--tom');
        },
        tom_sleep : function(){
            console.log('kanxingxing--tom');
        },
        tom_run : function(){
            console.log('run')
        }
    }
    
// 3.注册观察者(建立发布者和观察者之间的联系)
    rose.addUser(jack.jack_eat,'eat');
    rose.addUser(jack.jack_sleep,'sleep');
    rose.addUser(tom.tom_sleep,'sleep');
    rose.addUser(tom.tom_run,'run')
// 4. 发布者发布信息
    rose.eat();
    rose.sleep();
    rose.run();
// 5.移除观察者
    rose.removeUser(jack.jack_sleep.'sleep');
    rose.sleep();
观察者模式实现(发布者变为观察者) 05
  • 设计模式的目的是为了降低耦合度, 解耦
  • 特点: 两者可以互换,只要建立联系,创建发布者,就能让观察者称为发布者
// 1. 提供一个发布者模板
    var publisher = {
        addUser: function (fn,type){
            var type = type || 'eat';
            if(typeof fn != 'function') throw '非法操作';
            if(this.user[type] == undefined){
                this.user[type] = [];
            }
            this.user[type].push(fn);
        },
        removeUser: function(fn,type){
            if(typeof fn != 'function') throw '非法操作';
            var index = this.user[type].indexof(fn);
            this.user[type].splice(index,1)
        },
        // 发布信息
        publish : function (type){
            var type = type || 'eat'
            for(var i = 0 ; i< this.user[type].length; i++){
               this.user[type][i](); 
            }
        }
    };
    
    var rose = {
        eat: function(){
            this.publish('eat');
        },
        sleep: function(){
            this.publish('sleep')
        },
        run: function(){
            this.publish('run')
        },
        rose_lol : function(){
            console.log('nonono')
        }
    };
    var wml = {};
    
// 2.封装一个函数快速创建发布者
    function makePulisher(obj){
        for(var key in pushlisher){
            // 只需要拷贝实例方法
            if(publisher.hasOwnProperty(key) && (typeof publisher[key] == 'function')){ 
            obj[key] = publisher[key];
            }
        }
        // 手动添加
        obj.user = {};
    }
    
// 让rose成为发布者
    makePublisher(rose);
    
    // 2.提供一个观察者
    var jack = {
        jack_eat: function(){
            console.log('邀请女神吃大餐!--jack');
        },
        jack_sleep : function(){
             console.log('wanan!--jack');
        },
        lol : function (){
            this.publish('lol')
        }
    }
    
    var tom = {
        tom_eat : function(){
            console.log('邀请女神吃麻辣烫--tom');
        },
        tom_sleep : function(){
            console.log('kanxingxing--tom');
        },
        tom_run : function(){
            console.log('run')
        },
        tom_lol : function(){
            console.log('good')
        }
    }
    
    makePublish(jack);

    
// 3.注册观察者(建立发布者和观察者之间的联系)
    jack.addUser(rose.rose_lol,'lol');
    jack.addUser(tom.tom_lol,'lol');
    
    
// 4. 发布者发布信息
    jack.lol();