美文网首页
观察者模式 vs 订阅发布模式

观察者模式 vs 订阅发布模式

作者: ZuJung | 来源:发表于2018-07-24 00:54 被阅读0次

    一直很好奇订阅/发布模式和观察者模式有什么区别,一直以来都把这两者混为一谈。

    实际上,我理解中的观察者模式是1:n,而订阅发布模式是m:n的模式。观察者模式需要观察者直接在被观察这种注册,两者直接耦合,一般是同步的,而订阅发布模式则存在一个调度中心,观察者与被观察者不关心对方是谁,只通过消息通信,一般是异步的。

    观察者模式

    image.png
    class DownloadTask {
      private status: 'loadding' | 'finished' | 'pause' = 'loadding';
    
      constructor(public id: number, public taskName: string) {}
    
      public finish() {
        this.status = 'finished';
        console.log(`Task ${this.taskName} is notifed`);
      }
    
      public pause() {
        this.status = 'pause';
      }
    
      public start() {
        this.status = 'loadding';
      }
    }
    
    class DownloadList {
      public downloadList: DownloadTask[];
      constructor() {
        this.downloadList = [];
      }
    
      public add(task: DownloadTask) {
        this.downloadList.push(task);
      }
    
      public remove(id: number) {
        for (let task of this.downloadList) {
          if (task.id === id) {
            const index = this.downloadList.indexOf(task);
            this.downloadList.splice(index, 1);
          }
        }
      }
    
      public get(index: number) {
        return this.downloadList[index];
      }
    
      public length() {
        return this.downloadList.length;
      }
    }
    
    class DataHub {
      public downloadList = new DownloadList();
    
      public addDownloadTask(task: DownloadTask) {
        this.downloadList.add(task);
      }
    
      public removeDownloadTask(task: DownloadTask) {
        this.downloadList.remove(task.id);
      }
    
      public notify() {
        const len = this.downloadList.length();
    
        for (let i = 0; i < len; i++) {
          this.downloadList.get(i).finish();
        }
      }
    }
    
    
    
    const task1 = new DownloadTask(1, 'task1');
    const task2 = new DownloadTask(2, 'task2');
    
    const dataHub = new DataHub();
    
    dataHub.addDownloadTask(task1);
    dataHub.addDownloadTask(task2);
    
    dataHub.notify();
    

    订阅发布模式

    image.png
    class DownloadTask {
      private status: 'loadding' | 'finished' | 'pause' = 'loadding';
    
      constructor(public id: number, public taskName: string) {}
    
      public finish() {
        this.status = 'finished';
        console.log(`Task ${this.taskName} is notifed`);
      }
    
      public pause() {
        this.status = 'pause';
      }
    
      public start() {
        this.status = 'loadding';
      }
    }
    
    class DownloadList {
      public downloadList: DownloadTask[];
      constructor() {
        this.downloadList = [];
      }
    
      public add(task: DownloadTask) {
        this.downloadList.push(task);
      }
    
      public remove(id: number) {
        for (let task of this.downloadList) {
          if (task.id === id) {
            const index = this.downloadList.indexOf(task);
            this.downloadList.splice(index, 1);
          }
        }
      }
    
      public get(index: number) {
        return this.downloadList[index];
      }
    
      public length() {
        return this.downloadList.length;
      }
    }
    
    class DataHub {
      public downloadList = new DownloadList();
    
      public addDownloadTask(task: DownloadTask) {
        this.downloadList.add(task);
      }
    
      public removeDownloadTask(task: DownloadTask) {
        this.downloadList.remove(task.id);
      }
    
      public notify() {
        const len = this.downloadList.length();
    
        for (let i = 0; i < len; i++) {
          this.downloadList.get(i).finish();
        }
      }
    }
    
    class DepManager {
      public events: {
        [index: string]: ((...rest: any[]) => void)[];
      } = {};
    
      public registerChannel(evtName: string) {
        if (!this.events[evtName]) {
          this.events[evtName] = [];
        } else {
          console.error('already registed');
        }
      }
    
      public subscribe(evtName: string, cb: any) {
        if (this.events[evtName]) {
          this.events[evtName].push(cb);
        }
      }
    
      public emit(evtName: string, payload?: any) {
        if (this.events[evtName]) {
          try {
            const subscribers = this.events[evtName];
            for (let i = 0; i < subscribers.length; i++) {
              subscribers[i].call(null, payload);
            }
          } catch (e) {}
        }
      }
    }
    
    const task1 = new DownloadTask(1, 'task1');
    const task2 = new DownloadTask(2, 'task2');
    
    const taskList = new DownloadList();
    taskList.add(task1);
    taskList.add(task2);
    
    const manager = new DepManager();
    
    const dataHub = new DataHub();
    
    manager.registerChannel('datahub');
    
    manager.subscribe('datahub', () => {
      console.log('dispatch');
    });
    
    manager.emit('datahub');
    
    

    总结

    其实比较明显的地方在于观察者模式提供了一种点对多点的交互,但是当业务逻辑复杂的时候这种关系难以维护,因为需要单独对于被观察者进行注册,而订阅发布者模式则提供了一种统一事件管理方式,但相对的,实现所需要的成本则更高一些。

    注:
    以上的代码源自知乎:https://www.zhihu.com/question/23486749

    相关文章

      网友评论

          本文标题:观察者模式 vs 订阅发布模式

          本文链接:https://www.haomeiwen.com/subject/bdwsmftx.html