详解前端框架中的设计模式 | 青训营

89 阅读5分钟

1. 什么是设计模式

通俗来讲,就是日常使用设计的一种惯性思维。因为对应的这种思维,以及对具体的业务或者代码场景,有着具体的优势,而后成为行业中的一种“设计模式”。

2. 为什么使用设计模式

设计模式是各种业务场景的最佳实践,有助于我们在写日常业务中时,提高自身的思路。例如单例模式,就可以用于登陆框,模态框等场景。每种设计模式,必然有其适合应用的场景,灵活运用设计模式,可以提高代码的可维护性,还可提升自身思维能力。

3. 设计模式的基本准则

  1. 优化代码第一步:单一职责原则
  2. 让程序更稳定更灵活:开闭原则
  3. 构建扩展性更好的系统:里式替换原则
  4. 让项目拥有变化的能力:依赖倒置原则
  5. 系统有更高的灵活性:接口隔离原则
  6. 更好地扩展性:迪米特原则

4. 设计模式的种类

4.1创建型模式

一般用于创建对象。包括: 单例模式,工厂方法模式,抽象工厂模式,建造者模式,原型模式。

4.2结构型模式

重点为“继承”关系,有着一层继承关系,且一般都有“代理”。 包括:适配器模式,桥接模式,组合模式,装饰器模式, 外观模式,享元模式,代理模式,过滤器模式

4.3行为型模式

职责的划分,各自为政,减少外部的干扰。 包括:命令模式,解释器模式,迭代器模式,中介者模式, 备忘录模式,观察者模式,状态模式,策略模式, 模板方法模式,访问者模式,责任链模式

5. 前端常见的设计模式

5.1 外观模式

外观模式是最常见的设计模式之一,它为子系统中的一组接口提供一个统一的高层接口,使子系统更容易使用。简而言之外观设计模式就是把多个子系统中复杂逻辑进行抽象,从而提供一个更统一、更简洁、更易用的API。很多我们常用的框架和库基本都遵循了外观设计模式,比如JQuery就把复杂的原生DOM操作进行了抽象和封装,并消除了浏览器之间的兼容问题,从而提供了一个更高级更易用的版本。

5.1.1 应用场景

  • 设计初期,应该要有意识地将不同的两个层分离,比如经典的三层结构,在数据访问层和业务逻辑层、业务逻辑层和表示层之间建立外观Facade
  • 在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,增加外观Facade可以提供一个简单的接口,减少他们之间的依赖。

5.1.2 优点

  • 减少系统相互依赖。
  • 提高灵活性。
  • 提高了安全性

5.1.3 缺点

不符合开闭原则如果要改东西很麻烦,继承重写都不合适。

5.2 单例模式

顾名思义,单例模式中Class的实例个数最多为1。当需要一个对象去贯穿整个系统执行某些任务时,单例模式就派上了用场。而除此之外的场景尽量避免单例模式的使用,因为单例模式会引入全局状态,而一个健康的系统应该避免引入过多的全局状态。

5.2.1 应用场景

  • 定义命名空间和实现分支型方法
  • 登录框
  • vuex 和 redux中的store

5.2.2 优点

  • 划分命名空间,减少全局变量
  • 增强模块性,把自己的代码组织在一个全局变量名下,放在单一位置,便于维护
  • 且只会实例化一次。简化了代码的调试和维护

5.2.3 缺点

  • 由于单例模式提供的是一种单点访问,所以它有可能导致模块间的强耦合
  • 从而不利于单元测试。无法单独测试一个调用了来自单例的方法的类,而只能把它与那个单例作为一 个单元一起测试

5.3 工厂模式

工厂模式定义一个用于创建对象的接口,这个接口由子类决定实例化哪一个类。该模式使一个类的实例化延迟到了子类。而子类可以重写接口方法以便创建的时候指定自己的对象类型

5.3.1 应用场景

  • 如果你不想让某个子系统与较大的那个对象之间形成强耦合,而是想运行时从许多子系统中进行挑选的话,那么工厂模式是一个理想的选择
  • 将new操作简单封装,遇到new的时候就应该考虑是否用工厂模式;

5.3.2 优点

  • 创建对象的过程可能很复杂,但我们只需要关心创建结果。
  • 构造函数和创建者分离, 符合“开闭原则”
  • 一个调用者想创建一个对象,只要知道其名称就可以了。
  • 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。

5.3 .3 缺点

  • 添加新产品时,需要编写新的具体产品类,一定程度上增加了系统的复杂度
  • 考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度