关于js的设计模式

本文探讨了JavaScript中的常见设计模式,包括工厂模式(用于封装对象创建)、单例模式(确保类只有一个实例)、发布-订阅模式(用于事件传递)以及装饰器模式(动态添加功能)和策略模式(定义算法族,按需选择)。这些模式有助于提高代码的灵活性、可维护性和扩展性。
摘要由CSDN通过智能技术生成

在复习前端基础知识的过程中 总要追求一下js这个语言的本质 此文讨论一下常见的几种设计模式

首先 我们要知道 什么是设计模式?

举个例子 假如现在我们有一个房子 还有一堆杂七杂八的衣服裤子 那我们如果想把衣物保存在这个房子里面 方法有很多 最简单的就是直接放在地上 这样是最简单的方式 但是从另一个维护层面来讲 它又太杂乱了 不好梳理 那么我们可以选择买一个柜子来对这些衣物进行分类处理 虽然会多出买衣柜的钱 但是整理起来更加方便 看起来也更加整洁优雅 这就是两种设计模式

所谓设计模式,是前辈们总结下来的,在软件设计、开发过程中,针对特定场景、特定问题的较优解决方案。

常见的设计模式

1.工厂模式

工厂模式是一种用来创建对象的设计模式

我们知道 创建对象实例 是通过new关键字来调用的

那么工厂模式就是在不暴露创建对象的逻辑的情况下 也就是将创建对象的逻辑封装在函数内 那么这个函数就成为了工厂

那么这样有什么意义呢?

就是把一些复杂的逻辑和创建对象封装在一起 对外只要输入不同的参数 那么这个函数就会给你返回不同的对象 省去了繁杂的步骤 而且方便使用

如下:

function createPerson(name) {
  var people= new Object();
  people.name = name;
  people.age = "0"
  if (name === "zzz") {
    people.age= "18";
  }
  if (name === "xxx") {
    people.age= "180";
  }
  if (name === "lll") {
    people.age= "999";
  }
  return people;
}
var people1 = createPerson("zzz")
var people2 = createPerson("xxx")
var people3 = createPerson("lll")
console.log(people1);
console.log(people2);
console.log(people3);

可以看到我们传入不同的参数 返回对象的属性值都不相同 当然这只是简单的测试 实际可以封装更多更复杂的逻辑 工厂模式就显得尤为重要了

优缺点:

优点:

  1. 良好的封装,访问者无需了解创建过程,代码结构清晰。
  1. 扩展性良好,通过工厂方法隔离了用户和创建流程,符合开闭原则。
  1. 解耦了高层逻辑和底层产品类,符合最少知识原则,不需要的就不要去交流;

缺点:

给系统增加了抽象性,带来了额外的系统复杂度,不能滥用。(合理抽象能提高系统维护性,但可能会提高阅读难度,还是需要合理看待)

2.单例模式

单例模式就是保证一个类只有一个实例 实现的方法一般是先判断是否当前存在实例 如果存在 就直接返回 不在重新创造实例 如果不存在 就创建了再返回 保证一个实例的好处是可以减少不必要内存的开销

具体实现是创建函数 判断实例是否存在 如果存在 直接返回实例 并在实例上执行逻辑 这里借用一段代码 如下:

class Singleton {
    let _instance = null;
    static getInstance() {
        if (!Singleton._instance) {
          Singleton.instance = new Singleton()
        }
        // 如果这个唯一的实例已经存在,则直接返回
        return Singleton._instance
    }
}

const s1 = Singleton.getInstance()
const s2 = Singleton.getInstance()

console.log(s1 === s2)  // true

例如vue中vuex的原理就是单例模式的应用 通过Vue.use(Vuex)安装Vuex插件 Vuex插件本质上是一个对象,内部实现了一个install方法,这个方法在插件安装时被调用,从而把Store注入到Vue实例中。

let Vue // instance 实例

export function install (_Vue) {
  // 判断传入的Vue实例对象是否已经被install过(是否有了唯一的state)
  if (Vue && _Vue === Vue) {
    if (process.env.NODE_ENV !== 'production') {
      console.error(
        '[vuex] already installed. Vue.use(Vuex) should be called only once.'
      )
    }
    return
  }
  // 若没有,则为这个Vue实例对象install一个唯一的Vuex
  Vue = _Vue
  // 将Vuex的初始化逻辑写进Vue的钩子函数里
  applyMixin(Vue)
}

通过这种方式可以保证每个vue实例对象都只会被安装一次vuex插件    每一个vue实例只会拥有一个全局的store

优缺点

优点: 节约资源,保证访问的一致性。

缺点: 扩展性不友好,因为单例模式一般自行实例化,没有接口。

3.发布-订阅模式&观察者模式

我总认为这两个模式是相同的 这里来解释一下他们的区别

首先:实现二者所需的角色数量有着明显的区别。观察者模式本身只需要2角色便可成型,即观察者和被观察者,其中被观察者是重点。而发布订阅需要至少3角色来组成,包括发布者、订阅者、发布订阅中心,其中发布订阅中心是重点。

3.1观察者模式

类似于响应式 被观察者发生改变 那么观察者也可以发生改变 

优缺点

优点:目标变化就会通知观察者,这是观察者模式最大的优点。

缺点: 不灵活。目标和观察者是耦合在一起的,要实现观察者模式,必须同时引入被观察者和观察者才能达到响应式的效果。

3.2发布-订阅模式

发布订阅模式使用了一位中间人 也就是发布订阅中心 发布者和订阅者之间并没有直接联系 当发布者发布了新状态 那么发布订阅中心就会提醒订阅者

vue的双向数据绑定就是基于此实现的

通过DefineProperty劫持各个数据的settergetter,并为每个数据添加一个订阅者列表,这个列表将会记录所有依赖这个数据的组件。响应式后的数据相当于消息的发布者。

每个组件都对应一个Watcher订阅者,当组件渲染函数执行时,会将本组件的Watcher加入到所依赖的响应式数据的订阅者列表中。相当于完成了一次订阅,这个过程叫做“依赖收集”。

当响应式数据发生变化时,会出settersetter负责通知数据的订阅者列表中的WatcherWatcher触发组件重新渲染来更新视图。视图层相当于消息的订阅者。

4.装饰器模式

就是在不改变原对象的基础上 新增属性/方法  一层一层包裹

优点:

  1. 对象的核心职责和装饰功能区分开,可以通过动态增删装饰去除目标对象中的装饰逻辑。

5.策略模式

定义一系列算法 根据输入的参数选择使用哪个算法

例如 : 双十一满减活动。满200-20、满300-50、满500-100

可以使用if-else直接判断 但是如果逻辑多了 就会很臃肿 不够优雅 而且👇

                                                                            策略模式的重点是算法的实现和算法的使用分开

最开始我还不明白这句话什么意思 使用和实现不是一个意思吗??? 难道这不是策略模式吗??

后来看到大佬们优化的代码才知道👇

// 算法的实现
const discountMap = {
    'discount200-20': function(price) {
        return price - Math.floor(price / 200) * 20;
    },
    'discount300-50': function(price) {
        return price - Math.floor(price/300) * 50;
    },
    'discount500-100': function(price) {
        return price - Math.floor(price/500) * 100;
    },
}

// 算法的使用
function priceCalculate(discountType,price){
    return discountMap[discountType] && discountMap[discountType](price);
}

这样才叫策略模式 我的理解是先定义好算法 根据输入去查询这个算法是否存在 如果存在 就调用这个算法 如果不存在 我们还可以设置方法选择是否向其中添加算法

优缺点

优点:

  1. 策略相互独立,可以互相切换。提高了灵活性以及复用性。
  1. 不需要使用if-else进行策略选择,提高了维护性。
  1. 可扩展性好,满足开闭原则。

缺点:

  1. 策略相互独立,一些复杂的算法逻辑无法共享,造成资源浪费。
  1. 用户在使用策略时,需要了解具体的策略实现。不满足最少知识原则,增加了使用成本。

以上就是常见的几种设计模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值