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

观察者模式

Subject 和 Observer 直接绑定,中间无媒介。如点击事件,事件直接和按钮进行绑定。

发布订阅模式

Publisher 和 Observer 相互不认识,中间有媒介。如在 A 组件中绑定一个事件,在 B 组件中触发这个事件,这个两个组件相隔十万八千里互补认识,那么就通过中间event这个媒介来通讯。

发布订阅模式需要在代码中触发 emit ,而观察者模式没有 emit

手写观察者模式

import React, { useState, useEffect } from 'react';

// 观察者函数
const observer = (newValue) => {
  console.log(`Subject changed to ${newValue}`);
};
const SubjectComponent = () => {
  // 使用useState创建一个状态变量
  const [subject, setSubject] = useState('Initial Value');
  // 使用useEffect来模拟观察者模式
  useEffect(() => {
    // 当subject变化时,调用观察者函数
    observer(subject); 
  }, [subject]); // 依赖数组中包含subject,这样每当subject变化时,useEffect都会执行
  // 更新subject的方法
  const updateSubject = () => {
    setSubject('Updated Value');
  };
  return (
    <div>
      <p>Subject: {subject}</p>
      <button onClick={updateSubject}>Update Subject</button>
    </div>
  );
};

export default SubjectComponent;

手写发布订阅模式

发布-订阅模式是一种消息传递模式,允许发送者(发布者)发送消息,而不直接将其发送给特定的接收者(订阅者)。同样,接收者可以订阅一个或多个消息,而无需知道发送者的身份。这种模式在事件驱动编程中非常常见,比如浏览器的DOM事件、Node.js的事件等。

下面是一个简单的JavaScript实现发布-订阅模式的例子:

class PubSub {  
    constructor() {  
        this.subscribers = {};  
    }  
  
    // 订阅事件  
    subscribe(event, callback) {  
        if (!this.subscribers[event]) {  
            this.subscribers[event] = [];  
        }  
        this.subscribers[event].push(callback);  
    }  
  
    // 取消订阅事件  
    unsubscribe(event, callback) {  
        if (this.subscribers[event]) {  
            this.subscribers[event] = this.subscribers[event].filter(subCallback => subCallback !== callback);  
        }  
    }  
  
    // 发布事件  
    publish(event, data) {  
        if (this.subscribers[event]) {  
            this.subscribers[event].forEach(callback => callback(data));  
        }  
    }  
}  
  
// 使用示例  
const pubsub = new PubSub();  
  
// 订阅事件  
pubsub.subscribe('myEvent', data => console.log('Received data:', data));  
  
// 发布事件  
pubsub.publish('myEvent', 'Hello, world!'); // 输出: Received data: Hello, world!  
  
// 取消订阅事件  
pubsub.unsubscribe('myEvent', (data) => console.log('Received data:', data));  
  
// 再次发布事件,此时不会有输出,因为已经取消了订阅  
pubsub.publish('myEvent', 'Hello again!');

在这个例子中,我们创建了一个PubSub类,它有三个方法:subscribe、unsubscribe和publish。subscribe方法用于订阅事件,它将回调函数存储在一个以事件名为键的对象中。unsubscribe方法用于取消订阅事件,它从存储的回调函数中移除指定的回调函数。publish方法用于发布事件,它遍历所有订阅了该事件的回调函数,并调用它们。

react实现

// EventBus.js
import { createContext, useContext, useState } from 'react';

const EventBusContext = createContext();

export const EventBusProvider = ({ children }) => {
  const [events, setEvents] = useState({});

  const subscribe = (eventName, callback) => {
    if (!events[eventName]) {
      setEvents((prevEvents) => ({
        ...prevEvents,
        [eventName]: [],
      }));
    }
    setEvents((prevEvents) => ({
      ...prevEvents,
      [eventName]: [...prevEvents[eventName], callback],
    }));
  };

  const publish = (eventName, data) => {
    if (events[eventName]) {
      events[eventName].forEach((callback) => callback(data));
    }
  };

  return (
    <EventBusContext.Provider value={{ subscribe, publish }}>
      {children}
    </EventBusContext.Provider>
  );
};

export const useEventBus = () => useContext(EventBusContext);

js实现

let obj={};
//订阅
function on(id,fn){
    if(!obj[id]){
        obj[id]=[]
    }
    obj[id].push(fn)
}
//发布
function emit(id,msg){
    obj[id].foreach(fn=>fn(msg))
}

emit('lala','第一次发布')

on('lala','你好')
on('lala','我来了')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值