class Manager { constructor() { this.fans = []; this.works = []; } addFans(fan) { this.fans.push(fan); } setWorks(work) { this.works.push(work); // 添加作品后,调用更新方法 this.workUpdate(); } getWorks() { return this.works; } workUpdate() { this.fans.forEach((item) => item.update()); } }
嗯?这段代码貌似在哪儿见过?
没错,和2.2的Star类一模一样,只不过把类名改了改。
那这么做有意义吗?
事实上,代码一模一样是因为在2.2的Star类中我们只写了有关发布(即发布作品)和订阅(即维护粉丝列表)的功能;而Star类本身可能不止这个工作,比如创作内容。
现在我们将Star类中的发布和订阅的工作抽离出来,交给Manager全权负责。而Star类只要在创作完成后把作品交给Manager就可以了
另一方面,粉丝Fan也不再直接和Star发生交互了,Fan只关心能不能收到作品,所以Fan直接和Manager发生交互,Fan去订阅(这个行为相当于在Manager维护的粉丝列表中添加粉丝)Manager并从Manager那儿获取想要的作品
于是Star和Fan的代码如下:
class Star { constructor() {} // 创作 create(manager) { // 将创作的new work交给经纪人 manager.setWorks("new work"); } } class Fan { constructor(name, manager) { this.name = name; this.manager = manager; this.manager.addFans(this); } update() { console.log(`${this.name}:${this.manager.getWorks()}`); } }
5 发布订阅模式前面我们用了经纪人来负责发布和订阅的工作,而不让Star和Fan发生直接交互,达到了两者解耦的效果
这就是发布订阅模式
我们将4中的Manager进行进一步的抽象:
将“粉丝”看作订阅者(Subscriber);将“大V”看作内容的发布者,在发布订阅模式中称为发布者(Publisher);把“经纪人”看作发布订阅中心(或者说中间人Broker)
具体代码如下:
// 发布订阅调度中心 class Broker { constructor() { this.subscribers = []; // 代表主题状态 this.state = 0; } // 订阅 subscribe(subscriber) { this.subscribers.push(subscriber); } // 更改主题状态 setState(state) { this.state = state; // 状态改变后,发布 this.publish(); } getState() { return this.state; } // 发布 publish() { this.subscribers.forEach((subscriber) => subscriber.update()); } } // 发布者 class Publisher { constructor() {} changeState(broker, state) { broker.setState(state); } } class Subscriber { constructor(name, broker) { this.name = name; this.broker = broker; this.broker.subscribe(this); } update() { console.log(`${this.name}:${this.broker.getState()}`); } }
来运行一下看看效果:
// 创建调度中心 const broker = new Broker() // 创建发布者 const publisher = new Publisher() // 创建订阅者 const subscribe1 = new Subscriber('s1', broker) const subscribe2 = new Subscriber('s2', broker) const subscribe3 = new Subscriber('s3', broker) // 发布者改变状态并通知调度中心,调度中心就会通知各个订阅者 publisher.changeState(broker, 1)
6 观察者模式和发布订阅模式的对比从角色数量看
观察者模式只有两个角色:观察者和被观察者
发布订阅模式有三个角色:发布者、订阅者以及中间人(发布订阅中心)
从耦合程度看
观察者模式处于一种松耦合的状态,即两者依然有交互,但是又很容易各自扩展且不相互影响
发布订阅模式中的发布者和订阅者则完全不存在耦合,达到了对象之间解耦的效果
从意图来看
两者都:实现了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知并自动更新