观察者模式

当 主体的状态发生了改变  通知先关个体 相关个体的数据也同时发生改变更新

实际项目中,观察者模式需要与 框架中的 双向数据绑定 结合使用

观察者模式使用:

1.需要一个主体  实例化对象

2.需要一个消息盒子 存储所有需要执行的程序

3.on方法:

向消息盒子添加要执行的程序

1.执行的程序有 分类 也就是 事件类型
2.在事件类型,绑定添加 事件处理函数
3.将来这些 事件处理函数,还需要被删除,必须要添加事件处理函数的名称

添加的过程步骤--判断是否有这个类型

如果没有这个类型
创建这个类型,同时,添加事件处理函数
事件处理函数,以数组的形式存储
如果有这个类型
循环遍历,如果没有这个事件处理函数,我们再添加

4.off方法:删除消息盒子中,已经添加的方法

判断 类型是否存在

如果类型不存在
不再执行之后的程序
如果类型存在
循环遍历,如果事件名称存在,执行删除程序

5.emit方法:发布执行消息盒子中的方法

可以执行一个或者多个事件处理函数

而且还要保证,事件处理函数,是已经添加的事件处理函数,才会执行

需要两个参数

第一个参数是: 事件类型
第二个参数是: 所有需要执行的事件处理函数
    class Observer{
        constructor(){
            // 消息盒子
            this.msg = {};
        }
        // 向消息盒子添加要执行的程序
        // 参数1,事件类型
        // 参数2,事件处理函数的函数名称
        on( type , funName ){ 
            // 判断是否有这个类型
            if( this.msg[type] === undefined ){
                // 证明没有这个 事件类型 是 第一次添加
                // 直接向 消息盒子,添加类型,同时以数组的形式,存储事件处理函数名称
                this.msg[type] = [funName];
            }else{
                // 证明有这个 事件类型 不是 第一次添加
                // 循环遍历 事件类型 看 事件类型数组中 是否已经有了 事件处理函数名称
                // 如果没有,再添加
                let bool = true;
                // 循环遍历,v就是函数名称
                this.msg[type].forEach( v=>{
                    if(v === funName){
                        // 存储的函数名称 等于 添加的函数名称
                        bool = false;
                    }
                } )
                // 循环结束,如果bool还是true,证明事件类型数组中,没有要添加的函数名称
                if(bool){
                    this.msg[type].push( funName );
                } 
            }
        }
        // 删除消息盒子中已经添加的方法
        // 参数1:事件类型
        // 参数2:事件处理函数名称
        off(type,funName){
            if(this.msg[type] !== undefined){
                // 调用事件类型,不是undefined,证明事件类型存在,再执行程序
                this.msg[type].forEach( (v,k)=>{
                    // 如果 存储的名称 等于 输入的 函数名称
                    if( v === funName ){
                        // 数组删除单元,从当前索引开始删除,删除一个单元
                        this.msg[type].splice( k , 1);
                        // 没有重复数据,不用考虑数组坍塌的问题
                    }
                } )
            }
        }
        // 执行消息盒子中已经添加的方法
        // 参数1:事件类型
        // 参数2:所有需要执行的事件处理函数名称
        //       使用 ...合并运算符 以数组形式存储
        emit(type , ...funName){
            // 判断 事件类型 是否存在
            if( this.msg[type] !== undefined ){
                // v1 存储的函数名称
                this.msg[type].forEach( v1 => {
                    // v2 是 输入的参数,也就是要执行的函数名称
                    funName.forEach( v2 =>{
                        // 存储的,和要执行的函数名称,相同,我们才会执行
                        if( v1 === v2 ){
                            // 执行发布程序
                            v1();
                        }
                    })
                })
            }
        }
    }
    // 创建观察者模式主体,实例化对象
    const observer = new Observer();

    // 通过on方法,添加事件类型和事件处理函数名称
    observer.on( 'qing' , qingYeYe);
    observer.on( 'qing' , qingNaiNai);
    observer.on( 'qing' , qingBaBa);
    observer.on( 'qing' , qingMaMa);

    observer.on( 'moshou' , moshouPhone);
    observer.on( 'moshou' , moshouHeadset);
    observer.on( 'moshou' , moshouIpad);
    observer.on( 'moshou' , moshouPc);

    observer.on( 'jiancha' , jianchaBan);
    observer.on( 'jiancha' , jianchaJiao);
    observer.on( 'jiancha' , jianchaXiao);
    observer.on( 'jiancha' , jianchaJu);

    // 通过 off 方法 执行删除
    observer.off( 'jiancha' , jianchaJu);

    // 通过 emit方法 执行函数
    observer.emit( 'jiancha' , jianchaBan , jianchaJiao , jianchaXiao , abc );
    // 执行jianchaBan() jianchaJiao() jianchaXiao()方法
    // 不执行abc()方法
    console.log(observer);
    // Observer
    //     msg:
    //         jiancha: Array(3)
    //             0: ƒ jianchaBan()
    //             1: ƒ jianchaJiao()
    //             2: ƒ jianchaXiao()
    //             length: 3
    //             __proto__: Array(0)
    //         moshou: Array(4)
    //             0: ƒ moshouPhone()
    //             1: ƒ moshouHeadset()
    //             2: ƒ moshouIpad()
    //             3: ƒ moshouPc()
    //             length: 4
    //             __proto__: Array(0)
    //         qing: Array(4)
    //             0: ƒ qingYeYe()
    //             1: ƒ qingNaiNai()
    //             2: ƒ qingBaBa()
    //             3: ƒ qingMaMa()
    //             length: 4
    //             __proto__: Array(0)
    //         __proto__: Object
    //     __proto__: Object

    // 先定义事件处理函数
    // 请 类型 事件处理函数
    function qingYeYe(){
        console.log('我是请爷爷程序')
    }
    function qingNaiNai(){
        console.log('我是请奶奶程序')
    }
    function qingBaBa(){
        console.log('我是请爸爸程序')
    }
    function qingMaMa(){
        console.log('我是请妈妈程序')
    }

    // 没收 类型 事件处理函数
    function moshouPhone(){
        console.log('我是没收手机程序')
    }
    function moshouHeadset(){
        console.log('我是没收耳机程序')
    }
    function moshouIpad(){
        console.log('我是没收Ipad程序')
    }
    function moshouPc(){
        console.log('我是没收电脑程序')
    }

    // 写检查 类型 事件处理函数
    function jianchaBan(){
        console.log('我是交给班主任检查程序')
    }
    function jianchaJiao(){
        console.log('我是交给教导主任检查程序')
    }
    function jianchaXiao(){
        console.log('我是交给校长检查程序')
    }
    function jianchaJu(){
        console.log('我是交给教育局长检查程序')
    }

    function abc(){
        console.log('我是没有添加的程序')
    }

一沙一世界,一花一天堂。君掌盛无边,刹那成永恒。