SOURCE

/***
* 使用闭包外部不能直接访问,和修改 保证安全
* 使用对象减小全局变量,更好管理
**/

// 定义观察者
let Observer = (() => {
  var _messages = {};
  return {
//      注册信息接口
    regist: (type,fn) => {
       // 检测该类型是否已经创建,未创建则创建并添加函数
       if(typeof _messages[type] === 'undefined'){
          _messages[type] = [];
          _messages[type].push(fn);
       }else{
          // 已经创建,新增一个函数
          _messages[type].push(fn);
       }
    },
//      发布信息接口
    fire: (type,args) => {
       // console.log(_messages.test);
       // 方法未注册,不执行,或返回提示信息;
       if(!type){return;}
       // 定义消息信息
       let events ={
          type: type,
          args: args || {}
       },
           i = 0, // 消息动作循环的环境变量
           len = _messages[type].length;  // 消息动作的总长度
       // 遍历消息动作
      for(; i < len; i++){
         // console.log(typeof(_messages[type]))
         _messages[type][i].call(this, events);
      };
    },
//      移除信息接口
    remove: (type,fn) => {
       // 如果消息动作队列存在
       if(_messages[type] instanceof Array){
          // 从最后一个消息动作开始遍历
          let i = _messages[type].length - 1;
          for(; i >= 0; i--){
             // 如果存在则删除,巧妙的用&&进行判断
             _messages[type][i] === fn && _messages[type].splice(i, 1);
             // 如果类型没有方法则删除类型
             _messages[type].length === 0 && delete _messages[type];
          }
       }
    }
  }
})();

// // 注册动作(挂载事件)
// Observer.regist('test', (e)=>{
//    console.log(e.type, e.args.msg);
// });

// // 发布信息(调用事件)
// Observer.fire('test', {msg: '传递参数'});

// 学生类
class Student {
   constructor(result){
      this.result = result;
      this.say = this.say.bind(this);
      this.answer = this.answer.bind(this);
}
   // 答题动作
   say(){
      console.log(this.result);
   }
   // 回答问题方式
   answer(question){
      Observer.regist(question, this.say);// 注册参数问题
   }
   // 睡觉的学生取消对提问的监听
   sleep(question){
      console.log(this.result+" "+question +" "+ '已被注销');// 弹出提示
      Observer.remove(question ,this.say);// 取消老师对问题的监听
   }
}

// 老师类
class Teacher{
   ask(question){
      console.log('问题是:'+question); // 打印提示
      Observer.fire(question); // 发布问题
   }
}



let teacher = new Teacher();
let student1 = new Student('第1个学生回答问题'),
    student2 = new Student('第2个学生回答问题'),
    student3 = new Student('第3个学生回答问题');

student1.answer('什么是设计模式');
student1.answer('什么是观察者模式');
student2.answer('什么是设计者模式');
student2.answer('什么是设计者模式');
student3.answer('简述观察者模式');

student3.sleep('简述观察者模式');

teacher.ask('什么是设计模式');


console 命令行工具 X clear

                    
>
console