前端进阶-设计模式

1、创建型模式

创建型模式介绍的是:创建对象的机制, 能够提升已有代码的灵活性和可复用性。

简单工厂模式&工厂方法模式(常用)

负责创建所有的实例,依照不同的类型创建不同的对象

优点:

屏蔽了对象生成的时候的复杂性,产生/构建产品比较简单,不需要关注内部细节,只需要知道自己想要哪一种。
缺点:
产品数量一旦特别多的时候,工厂内部逻辑会比较复杂,不利于理解和维护

javascript 复制代码
//Fruit类(产品类):
public interface Fruit {
    public void plantProcess();
}
定义三种水果Apple,Pear,Orange:
public class Apple implements Fruit{
    public void plantProcess() {
        System.out.println("I am an Apple");
    }
}
public class Pear implements Fruit{
    public void plantProcess() {
        System.out.println("I am a Pear");
    }
}
public class Orange implements Fruit{
    public void plantProcess() {
        System.out.println("I am an Orange");
    }
}
//工厂类:
public class FruitFactory {
    public static getFruit(String name) {
        if ("Apple".equalsIgnoreCase(name)) {
            return new Apple();
        } else if ("Pear".equalsIgnoreCase(name)) {
            return new Pear();
        } else if ("Orange".equalsIgnoreCase(name)) {
            return new Orange();
        }
        return null;
    }
}

//测试代码

Fruit apple = FruitFactory.getFruit("Apple");
apple.plantProcess();
Fruit pear = FruitFactory.getFruit("Pear");
pear.plantProcess();
Fruit orange = FruitFactory.getFruit("Orange");
orange.plantProcess();
    

案例

根据不同的用户角色(如'admin', 'editor', 'guest')创建不同的用户操作菜单组件

抽象工厂模式(不常用)

为一个抽象类,定义了基本的方法,但无需指定实现,根据产品类去实现。

单列模式(常用)

一个类只有一个实例, 并提供一个访问该实例的全局节点。

案例

像 Vuex 或 Redux 这样的状态管理库,其核心的 store 就是一个单例。像 MessageNotification 这样的全局提示组件,通常会使用单例模式来管理它们的实例。

javascript 复制代码
class Single{
    public static instance
    privite constructor(){}
    public static getInstance(){
        if(!Single.instance){
            Single.instance = new single()
        }
        return Single.instance
    }
    public methods(){}
}

//使用
let instance = Single.getInstance()

原型模式(不常用)

能够复制已有对象, 而又无需使代码依赖它们所属的类

生成器模式(不常用)

分步骤(一种组合的方式)创建复杂对象(产品)

2、结构型模式

结构型模式介绍如何将对象和类组装成较大的结构, 并同时保持结构的灵活和高效。

适配器模式(常用)

使接口 不兼容的对象接口能够相互合作。
目标对象a接口需要与对象b接口对接时,存在 不兼容的问题。通过某些处理操作(适配器),使得对象b接口适配目标对象a接口。

案例

  • 跨浏览器兼容
  • 整合第三方的sdk
  • 新老代码兼容

装饰器模式(常用)

扩展目标对象中方法的功能,形成新的类。
在不改变原对象的基础上,通过对其进行包装拓展,使得原有对象可以动态具有更多功能,从而满足用户的更复杂需求。

桥接模式(常用)

可将业务逻辑或一个大类或一系列紧密相关的类拆分为不同的层次结构, 从而能独立地进行开发。

案例

  • 如果你想要拆分或重组一个具有多重功能的庞杂类 (例如能与多个数据库服务器进行交互的类), 可以使用桥接模式。
  • 如果你希望在几个独立维度上扩展一个类, 可使用该模式。 桥接建议将每个维度抽取为独立的类层次。 初始类将相关工作委派给属于对应类层次的对象, 无需自己完成所有工作。

代理模式(不常用)

让你能提供真实服务对象的替代品给客户端使用。 代理接收客户端的请求并进行一些处理 (访问控制和缓存等), 然后再将请求传递给服务对象。

案例

图片预加载(loading 图),图片懒加载

外观模式(不常用)

基于已有的类方法封装一些新的方法(创建一些新的功能)

3、行为模式

行为模式负责对象间的高效沟通和职责委派。

观察者和发布-订阅者模式(必考)

参考观察者和发布-订阅者模式

JS中观察者模式与发布订阅模式关于观察者模式与发布/订阅模式,不少大神都有帖子对他们做出了解释,但是很多文章都将两者混在 - 掘金

在观察者模式中订阅者和观察者是同一个类,它整个模式只有:发布者,观察者

事件总线(事件中心)

订阅,eventHub.$on(方法名,function(接收数据的参数){用该组件的数据接收传递过来的数据})

发布,eventHub.$emit(方法名,传递的数据)

取消发布,eventHub.$off(方法名,函数名称)取消订阅,要给函数一个名字,不能为匿名函数

javascript 复制代码
ts的规范写法:
export class EventBus<T = any> {
// 定义一个事件中心[事件名:订阅者[],]
   private listeners = new Map<string, Set<any>>();
   //private anyListeners = new Set<any>();
//发布
   $emit (eventName: string, ...args: T[]) {
      const listeners = this.listeners.get(eventName)
      if (!listeners) {
        return
      }
      listeners.forEach((listener) => {
        listener(...args)
      })
      //this.anyListeners.forEach((listener) => {
      //  listener(eventName, ...args)
      //})
    }
订阅
    $on (eventName: string, func: any) {
      if (!this.listeners.has(eventName)) {
        this.listeners.set(eventName, new Set())
      }
// 通过键名获取到的是对应的值(订阅一个事件:即为该事件名对应的set对象添加一个订阅者)
      const listeners = this.listeners.get(eventName)
      listeners!.add(func)
    }

     // onAny (func: any) {
     //   this.anyListeners.add(func)
     // }
    $off (eventName: string, func: any) {
        const listeners = this.listeners.get(eventName)
        listeners.delete(func)
     }
}

vue2双向数据绑定

组成

观察者Observer:用来劫持并监听所有属性,如果有变动的,就通知订阅者,如果有获取就添加订阅者。

订阅器:含有一个订阅者列表,及通知订阅者更新的函数,

订阅者Watcher(这么理解:观看的就是订阅者吧): 每一个Watcher都绑定一个更新函数,watcher可以收到属性的变化通知并执行相应的函数,从而更新视图。

编译器Compile:可以扫描和解析每个节点的相关指令(v-model,v-on等指令),如果节点存在v-model,v-on等指令,则解析器Compile初始化这类节点的模板数据,使之可以显示在视图上,然后初始化相应的订阅者(Watcher)。

关系说明:

基础版:

思想:数据劫持+发布订阅者模式

数据劫持:当将一个普通js的对象作为vue实例的data项,vue将遍历此对象的所有property并通过Object.defineProperty的getter,setter将所有的key进行劫持。

关系说明:

  • 每一个key都对应一个setter(),getter()函数和订阅器dep实例,
  • get函数:当key的获取函数getter()被触发时,就会创建一个watcher实例,存储到订阅器dep实例的数组中。
  • set 函数:当key的修改函数setter()被触发时,就会触发订阅器dep中的notify()函数,通知所有依赖该key的组件订阅者进行更新,通知组件实例更新:。
  • 订阅器dep实例中有个subs\[\]数组中存放着所有依赖该key(订阅者),及notify函数

进阶版:

  • 利用Object.definePropertygetset进行数据劫持
  • 利用observe遍历data数据来进行监听,并为数据创建dep实例来收集依赖
  • 利用Compiledom中的所有节点进行编译,并为组件添加wathcer实例
  • 通过dep&watcher发布订阅模式实现数据与视图同步

策略模式(常用)

具体它将一组行为转换为对象, 并使其在原始上下文对象内部能够相互替换

命令模式

职责链(责任链)模式

状态模式

访问者模式

迭代器模式

相关推荐
AI人工智能+电脑小能手18 小时前
大白话说Java设计模式-23-桥接模式(源码剖析篇)
java·设计模式·jdbc·桥接模式·源码分析·awt·java logging
嘟嘟071720 小时前
TypeScript 工具类型通关:Pick、Omit、Partial、Record 区别与 Omit 等价实现一次讲清
设计模式·面试·typescript
SL_staff21 小时前
中小离散制造如何用工艺路线模板解决‘人走流程丢’——JVS-APS 实践解析
java·设计模式·全栈
Asize21 小时前
3 种设计模式 + DI:Nest.js 后端第一课
后端·设计模式·nestjs
St_rive1 天前
Page Object设计模式
java·开发语言·设计模式
烬羽2 天前
NestJS 依赖注入:Controller 里那个没有 new 的 service,到底从哪来的?
设计模式·typescript·nestjs
用户938515635072 天前
工厂模式与 Nest.js 核心思想 —— 从蜜雪冰城到企业级架构
后端·设计模式·nestjs
烬羽3 天前
从 nest new 到 Hello World:一个最小 NestJS 项目,讲透工厂 + 装饰器 + 模块化
设计模式·node.js·nestjs
艺艺生辉4 天前
从if-else到策略模式
后端·设计模式
小林ixn4 天前
单例模式:从弹窗管理到全局状态,一个模式搞定
前端·javascript·设计模式