观察者模式,事件,监听,触发与推送
理论知识
观察者模式和发布订阅模式其实是一个东西,区别只是在于调度中心。

观察者模式定义了一种一对多的依赖关系,让多个观察者对象(或订阅者对象)同时监听同一个主题。这个主题对象在状态发送变化时,会通知所有的观察者对象(或订阅者对象),使得它们能够自动更新自己。
调度中心的作用之一,每个观察者对象(或者订阅者对象)的行为可能都不一样(方法名不一样),这个时候调度中心就能发挥作用,它提供“事件委托”的功能,主要是提供回调函数的关联。
两个问题
如何实现一个观察者模式
- 非典型的例子,这并不是一个观察者模型 ```javascript // index3.jsx interface EventType { eventName: string; eventFn: (…args: any[]): any; }
class EventBus { const listeners: EventType[] = []; // 添加一个事件(主题) addEvent(event: EventType){} // 移除一个事件(主题) removeEvent(eventName){} // 触发一个事件(通知,主题发生了变化) trigger(eventName){} }
export const eventBus = new EventBus;
// index2.js import { eventBus } from ‘./index3.jsx’; import React from ‘react’; class ClassA extends React.Component { constructor(props) { super(props); this.state = { num: 0, } } componentDidMount(){ eventBus.addEvent({ eventName:’numOnchange’, // 订阅一个主题 eventEvent: () => { this.setState({ num: num + 1, }); } }) } render(){ return (
// index1.js import { eventBus } from ‘./index3.jsx’; import React from ‘react’; class ClassB extends React.Component { constructor(props) { super(props); } render(){ return (
为什么观察者模式可以实现数据的传递(状态的自动更新)<a name="QXYDc"></a>##<a name="PZzGr"></a>## 值的拷贝与值的引用[https://www.yuque.com/lijunyang/dk90s4/qdxd19#919b86d2](https://www.yuque.com/lijunyang/dk90s4/qdxd19#919b86d2)<a name="Cq0Bi"></a>#### 观察者,被观察者(主题)```javascript// 观察者class Observer {constructor() {}update(val) {}}// 观察者列表(目标)class ObserverList {constructor() {this.observerList = []}add(observer) {return this.observerList.push(observer);}remove(observer) {this.observerList = this.observerList.filter(ob => ob !== observer);}count() {return this.observerList.length;}get(index) {return this.observerList(index);}}// 主题(目标)class Subject {constructor() {this.observers = new ObserverList();}addObserver(observer) {this.observers.add(observer);}removeObserver(observer) {this.observers.remove(observer);}notify(...args) {let obCount = this.observers.count();for (let index = 0; index < obCount; index++) {this.observers.get(i).update(...args);}}}const subject = new Subject();const classA = new Observer();const classB = new Observer();Subject.addObserver(classA);Subject.addObserver(classB);Subject.notify('发送一个字符串');
有趣的思路
如果将上面的代码与两个问题里的非典型的例子进行组合
// index3.jsxinterface EventType {eventName: string;eventFn: (...args: any[]): any;}interface EventData {eventName: string;paramData: any;}class EventMonitor {listeners = [];remove = function(eventName) {const arr = this.listeners.filter((temp) => {return temp.eventName !== eventName;});this.listeners = arr;}trigger = function(eventName, param) {this.listeners.forEach((item) => {if (eventName === item.eventName) {item.fn(param);}})}on = function(eventName, fn) {this.listeners.push({eventName,fn});}}class EventBus {const listeners: EventType[] = [];// 添加一个事件(主题)addEvent(event: EventType){}// 移除一个事件(主题)removeEvent(eventName){}// 触发一个事件(通知,主题发生了变化)trigger(eventName){}}
调度中心
class PubSub {constructor() {this.subscribers = {}}subscribe(type, fn) {if (!Object.prototype.hasOwnProperty.call(this.subscribers, type)) {this.subscribers[type] = [];}this.subscribers[type].push(fn);}unsubscribe(type, fn) {let listeners = this.subscribers[type];if (!listeners || !listeners.length) return;this.subscribers[type] = listeners.filter(v => v !== fn);}publish(type, ...args) {let listeners = this.subscribers[type];if (!listeners || !listeners.length) return;listeners.forEach(fn => fn(...args));}}let ob = new PubSub();ob.subscribe('add', (val) => console.log(val));ob.publish('add', 1);
一个应用场景

abstract class Subject {private IList<Observer> observers = new List<Observer>();// 增加观察者public void Attach(Observer observer) {observers.Add(observer);}// 删除观察者public void Detach(Observer observer) {observers.Remove(observer);}// 通知public void Notify() {foreach (Observer o in observers) {o.Update();}}}abstract class Observer {// 更新状态public abstract void Update();}class ConcreteSubject : Subject {// 具体被观察者的状态private string subjectState;public string SubjectState {get { return subjectState; }set { subjectState = value; }}}class ConcreteObserver : Observer {private string name;private string observerState;private ConcreteSubject subject;public ConcreteObserver(ConcreteSubject subject, string name) {this.name = name;this.subject = subject;}public override void Update() {observerState = subject.subjectState;Console.WriteLine("观察者{0}的新状态是{1}", name, observerState);}public ConcreteSubject Subject {get { return subject; }set { subject = value; }}}static void Main() {ConcreteObserver s = new ConcreteObserver(); // 创建一个主题s.Attach(new ConcreteObserver(s, "X"));s.Attach(new ConcreteObserver(s, "Y"));s.Attach(new ConcreteObserver(s, "Z"));s.SubjectState = "ABC"; // 设置状态s.Notify(); // 通知}/*结果显示观察者X的新状态是ABC观察者Y的新状态是ABC观察者Z的新状态是ABC*/
