【JS基础】浅浅了解下前端所需要的一些常用设计模式,提供例子说明

前言

目前没精力深入了解,所以先简单记录一些比较常用的设计模式。

日后有空了,待我深入了解后再更新文章~


工厂模式

大白话来说就是,定义了一个函数,这个函数相当于一个工厂,你需要什么样的产品,就输入什么样的参数,最终它给你生产出来。

例如:

  • React createElement函数
  • JQ的$()
  • 你自己封装的构造函数

拿构造函数来说,例如你封装了很多可以归为一个大类的class:

class IntNum {...}
class AntNum {...}
class TelNum {...}
// ... 等等

咱们可以把这堆关于不同类型数据处理的类,归纳成一个构造函数:

function GetTypeNumClass(type) {
	// ... 根据不同类型,return一个new class
}

这就是一个最简单的工厂模式写法


单例模式

主要特点是只能生成全局的唯一实例,并且提供一个能访问他的全局访问点。

例如:

  • vuex的store

面试可能会让你用es5实现,我这里贴出一个实现方式,如果不是奔着面试可以不用记

var Test = (function () {
  var instance = null;
  return function (name) {
    if (instance) {
      return instance;
    }
    this.name = name;
    instance = this;
    // return this;
  };
})();

var a = new Test("a");
var b = new Test("a");
Test.prototype.say = function () {
  alert(0);
};
var c = new Test("a");
console.log(a == b, b == c);

说明:利用了函数包裹立即执行创建了一个单独的作用域,并且将实例变量提升到最高层作用域上,最后在返回的函数中作为一个构造函数,里面吧this指向赋值给实例变量。

我们还是来看看真正在业务中要怎么使用,给个小例子,在TS中可以通过class加修饰符去写:

class SingleTon {
	private static instance: SingleTon | null = null
    private constructor() {}
    public static getInstance(): SingleTon {
        if (this.instance === null) {
            this.instance = new SingleTon()
        }
        return this.instance
    }
    fn1() {}
    fn2() {}
}

const a = SingleTon.getInstance()
a.fn1()
a.fn2()

const b = SingleTon.getInstance()
console.log(a === b); // 实例化出来的对象是同一个
  • public:表示公有,在父类定义函数中和外,以及子类都能直接以任何形式访问。
  • private:表示私有,只有在父类定义函数中访问,子类函数内部无法访问(但可通过外面调用继承的父类方法去访问)。

修饰符详细可以参考: 【TS基础】个人学习记录4-类的定义、继承、修饰符、静态、只读、多态、抽象

结合业务,例如我需要在一个应用中创建一个Websocket实例,供各个地方使用,但信息的收发都是必须由同一个Websocket实例来做,此时,单例模式就非常适用。我写个demo:

import { Socket } from "socket.io-client";
import io from "socket.io-client";

export class WebSocketSingleton {
  private static instance: WebSocketSingleton;
  private socket: Socket | null = null;
  public isInitData: boolean = true; // 添加自定义属性

  private constructor() {
    this.socket = io(appConfig.DEV_RAM_AXIOS_BASE_URL);
	// 监听数据
    this.socket.on("message", (msg) => {
      console.log(this.isInitData ? "-----init" : "-----update", msg);
      // this.isInitData = false;  修改自定义属性
    });
  }

  public static getInstance(): WebSocketSingleton {
    if (!WebSocketSingleton.instance) {
      WebSocketSingleton.instance = new WebSocketSingleton();
    }
    return WebSocketSingleton.instance;
  }
	
  // 发送数据
  public sendMessage(data: any) {
    if (this.socket) {
      const json = JSON.stringify(data);
      this.socket.emit("send_message", json);
    }
  }
}

在各个文件中可以这样使用:

// 引入省略...

const wsInstance = WebSocketSingleton.getInstance();
wsInstance.sendMessage(data);

在JavaScript这样的单线程环境下,实现单例模式相对容易。因为在任何时候,只有一个操作(一个线程)在运行,所以我们不需要担心多个线程同时去创建单例对象的问题。这意味着我们不需要加入额外的同步控制来保护单例创建的过程。

但是在多线程的环境下,比如Java,实现单例模式就要复杂一些了。在这样的环境下,可能存在多个线程同时尝试创建单例的情况,这会导致多个实例的产生,违反了单例模式只有一个实例的规则。为了防止这种情况,我们需要用到同步控制,例如使用synchronized关键字或者Lock接口,来确保在生成单例对象时只有一个线程能够执行,避免多实例的问题(GPT回答)。


代理模式

就是你想访问一个对象是无法直接访问的,只能通过一个代理层去访问。

例如:

  • proxy,通过get和set的触发进行访问

观察者模式

例如:

  • 平时加的监听器addEventListener
  • MutationObserver的使用。

举个业务中的例子,你需要监听一个DOM的变化,就可以用MutationObserver观察者模式去处理。

它创建一个观察者实例,用来观察一个DOM元素,并在它或它的子元素发生变化时被通知。这是观察者模式的一个很好的实践。

MutationObserver(观察者)观察DOM元素(主题),并在元素发生变动时接收到通知。

以下是一个简单的使用示例:

// 创建一个观察者实例
const observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    console.log(mutation.type); // 输出变动类型
  });    
});

// 配置观察选项:
const config = { attributes: true, childList: true, characterData: true }

// 在目标节点上开始观察:
observer.observe(target, config);

// 之后,你可以停止观察
// observer.disconnect();

在这个例子中,我们创建了一个观察者实例来观察目标节点的改变。当被观察的target发生变化时,观察者的回调函数会被触发并输出变动类型。


发布订阅模式

例如:

  • vue的bus机制

和观察者模式的区别:

  • 观察者模式,我认为触发主体和接收者是强绑定的,例如按钮和点击事件,二者关联性强。
  • 发布订阅模式,我认为触发的主体和接收者无需强绑定,接收者只和事件总线强绑定。

装饰器模式

相当于给原来的一些东西新附上一些功能

例如:

  • class和方法等的修饰符
  • ts的decorator语法

尾巴

多了解一些设计模式,你才能设计出高级的代码。中级前端和高级前端之间相差的其中一个维度就是代码设计。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值