聊聊设计模式(二)--迭代器模式,工厂模式,中介者模式,发布订阅模式

        设计模式,面试必考的问题之一,许多新入行的同学可能感觉很高大上,然而其实日常开发中我们也或多或少的使用着设计模式,只是可能大家没有感知到,今天我们就来聊聊常见的一些设计模式和该模式在前端的使用场景!

迭代器模式

首先来看概念

迭代器模式定义: 提供一种方法顺序访问一个对象中的各元素,而又不需要暴露该对象
的内部表示

迭代器模式可以简单理解为提供一个方法 完成forEach循环,对于js以及很多现代语言来说,都已经实现了内置迭代器模式

使用场景就很清晰:

只要需要遍历的场景都会使用到迭代器模式,可以把迭代的过程从业务逻辑中分离出来,而不用关心对象的内部结构

下面我们基于for循环简单实现一个迭代器模式

const myForEach = (arr, callback) => {
    for (let i =0; i < arr.length; i++) {
        callback.call(arr[i], i, arr[i])
    }
}

// 测试
myForEach ([1,2,3], function(i,n){ console.log([i,n]) })

ps: 迭代器模式是一种相对简单的模式,绝大多数语言都已经内置了迭代器模块,我们只需要知道有这个模式就行

 工厂模式

首先来看概念

工厂模式是最常用的一种用于创建对象的设计模式,其核心就是将逻辑封装在一个函数中不暴露创建对象的具体逻辑

简单来说,我们只要不让用户看到具体创建对象逻辑的方式,都可以称之为工厂模式,就类似工厂流水线,用户只能看到成品,看不到生产过程

基于这个实现思路也很多,我们简单使用构造函数实现下 

class factory {
  constructor (name, age) {
     this.name = name
     this.age = age
  }
  doSth () {
    alert(`我的名字${this.anem},我的年龄${this.age}`)
  }
}

const test1 = new factory ('张三', 18)
test1.doSth()

使用场景:  了解决多个类似对象声明

中介者模式

 首先来看概念

中介者模式允许对象之间通过中介者对象进行通信,而不是直接相互引用

其实类似代理模式,都是通过第三方实现通讯,而不是直接访问对象,这种模式有助于减少对象之间的耦合性,使代码更加可维护和可扩展。

我们简单实现下中介者模式 

/ 创建中介者对象
const Mediator = {
  // 注册对象
  participants: [],
  
  // 添加参与者
  addParticipant(participant) {
    this.participants.push(participant);
  },
  
  // 发送消息
  sendMessage(message, sender) {
    for (let participant of this.participants) {
      if (participant !== sender) {
        participant.receiveMessage(message);
      }
    }
  }
};

// 创建参与者对象
const Participant = {
  // 初始化参与者
  init(name) {
    this.name = name;
    Mediator.addParticipant(this);
  },
  
  // 接收消息
  receiveMessage(message) {
    console.log(`${this.name} 收到消息:${message}`);
  },
  
  // 发送消息
  sendMessage(message) {
    Mediator.sendMessage(message, this);
  }
};

// 创建参与者
const participant1 = Object.create(Participant);
participant1.init('参与者1');

const participant2 = Object.create(Participant);
participant2.init('参与者2');

// 发送消息
participant1.sendMessage('你好!');
participant2.sendMessage('你好,参与者1!');

ps: 了解中介者模式即可,实际工作中使用较少 

发布订阅模式 (观察者模式)

首先来看概念

发布订阅模式定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知

简单理解就是,所有用户订阅一个对象,这个对象发生变化时候,所有参与订阅的用户都会得到通知,就类似订阅公众号一样,有什么信息都会推送给订阅的用户

这是比较重要的一种设计模式, 我们熟悉的vue中的object.definePorperty就是典型使用了发布订阅模式

我们简单来看下object.definePorperty

const test = {
    name: '张三',
    age: 18
}
// 核心逻辑大致如下
object.keys(test).forEach((key) => {
  Object.defineProperty(test, key, {
    enumerable: true,
    configurable: true,
    get: () => {
      console.log('获取到修改的数据');
    },
    set: (newName) => {
      console.log('执行修改操作');
    },
  });
});

test.name = '李四'
console.log(test)

 其中: 

  • enumerable:对象属性是否可通过 for-in 循环,false 为不可循环,默认值为 true
  • configurable:能否使用 ·、能否需改属性特性、或能否修改访问器属性,false 为不可重新定义,默认值为 true

 这块拓展下,vue3使用了proxy代理来取代object.definePorperty

至于为什么要选择proxy,已经成为老生常谈的面试题了,这块小伙伴们估计比我清楚,我就简单总结两点,其余的大家可以补充

首先,object.definePorperty不能监听到数组的变化,而且必须遍历对象的每个属性,比较耗费内存

proxy是js原生属性,直接代理整个对象,这样就减少了遍历属性的过程

 最后,我们简单实现一个发布订阅模式

// 创建观察者对象
class Observer {
  constructor() {
    this.observers = [];
  }

  // 添加观察者
  addObserver(observer) {
    this.observers.push(observer);
  }

  // 移除观察者
  removeObserver(observer) {
    const index = this.observers.indexOf(observer);
    if (index !== -1) {
      this.observers.splice(index, 1);
    }
  }

  // 通知观察者
  notify(data) {
    for (let observer of this.observers) {
      observer.update(data);
    }
  }
}

// 创建具体观察者对象
class ConcreteObserver {
  update(data) {
    console.log(`收到更新:${data}`);
  }
}

// 创建被观察者对象
class Subject {
  constructor() {
    this.observers = new Observer();
  }

  // 添加观察者
  addObserver(observer) {
    this.observers.addObserver(observer);
  }

  // 移除观察者
  removeObserver(observer) {
    this.observers.removeObserver(observer);
  }

  // 发送通知
  notifyObservers(data) {
    this.observers.notify(data);
  }
}

// 创建观察者和被观察者对象
const observer1 = new ConcreteObserver();
const observer2 = new ConcreteObserver();
const subject = new Subject();

// 添加观察者到被观察者
subject.addObserver(observer1);
subject.addObserver(observer2);

// 发送通知
subject.notifyObservers('Hello World!');

// 移除观察者
subject.removeObserver(observer2);

// 再次发送通知
subject.notifyObservers('Goodbye!');

总结一下,发布订阅模式的优缺点

优点: 支持简单的广播通信。当对象状态发生改变时,会自动通知已经订阅过的对象

          发布者与订阅者的耦合性降低

缺点:  耗时耗内存。创建订阅者需要消耗一定的时间和内存

           维护相对困难

ps: 最近公司事比较多,更新不及时,实在抱歉

  • 41
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值