【前端八股】设计模式前置知识

109 阅读6分钟

一、什么是设计模式?

在前端开发中,设计模式是解决特定问题的经验总结和可复用的解决方案,可以提高代码的复用性、可维护性和可读性,是提高开发效率的重要手段。

设计模式并不直接用来完成代码的编写,而是描述在各种不同情况下,要怎么解决问题的一种方案。

设计模式能使不稳定依赖于相对稳定、具体依赖于相对抽象,避免会引起麻烦的紧耦合,以增强软件设计面对并适应变化的能力。

因此,当我们遇到合适的场景时,我们可能会条件反射一样自然而然想到符合这种场景的设计模式。

二、设计模式的七大原则

1. 单一职责原则

单一职责原则 (Single responsibility principle) ,即一个类应该只负责一项职责

例如,类A负责两个不同职责:职责1,职责2。当职责1需求变更而改变A时,可能造成职责2执行错误,所以需要将类A的粒度分解为A1,A2。

注意事项和细节

  • 降低类的复杂度,一个类只负责一项职责
  • 提高类的可读性,可维护性
  • 降低变更引起的风险
  • 通常情况下,我们应当遵守单一职责原则,只有逻辑足够简单,才可以在代码级违反单一职责原则;只有类中方法数量足够少,可以在方法级别保持单一职责原则

2. 接口隔离原则

接口隔离原则 (Interface Segregation Principle) ,即客户端不应该依赖于它不需要的接口,即一个类对另一个类的依赖应该建立在最小接口上

image.png

image.png

3. 依赖倒转原则

依赖倒转原则 (Dependence Inversion Principle) 的中心思想是面向接口编程,所谓“倒转”是指抽象不应该依赖细节,而是细节应该依赖抽象。也就是高层模块不应该依赖低层模块,二者都应该依赖其抽象。

依赖倒转原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。

变量的声明类型尽量是抽象类或接口,这样变量引用和实际对象间,就存在一个缓冲层,利于程序扩展和优化。使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给实现类完成。

栗子.png 举一个栗子

比如有个Person类,可以接受Email、QQ和微信的消息。如果都为其提供一个专门的方法,就会让代码非常的冗余:

image.png

可以引入一个IReceiver接口,让Person类依赖该接口。这样QQ、微信和Email各自实现IReceiver里面的方法即可:

image.png

4. 里氏替换原则

里氏替换原则 (Liskov Substitution Principle) 要求所有引用基类的地方必须能透明地使用其子类的对象。也就是在继承关系中,子类尽量不要重写父类的方法

继承实际上让两个类耦合性增强了,特别是运行多态比较频繁时,整个继承体系的复用性会比较差。

栗子.png 举个栗子

B类继承了A类,但却重写了大部分方法,那么继承的意义何在?说好的复用呢?

image.png

解决方法是把原来的父类和子类都继承一个更通俗的基类,在适当的情况下,可以通过聚合,组合,依赖等来代替。

image.png

5. 开闭原则

开闭原则 (Open Closed Principle) 是编程中最基础、最重要的设计原则。

一个软件实体,如类,模块和函数应该对扩展开放,对修改关闭 。用抽象构建框架,用实现扩展细节。

当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。

编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则。

栗子.png 举个坏栗子

矩形 (Retangle) 和圆形 (Circle) 继承了图形类 (Shape),画图类 (GraphicEditor) 会调用相关属性

image.png

但是如果再新增一个三角形,就要在使用方GraphicEditor新增对应方法,修改地方较多,违背开闭原则。

image.png

改进.png 改进

把Shape做成抽象类并提供抽象方法draw,让子类去实现即可。当新增图形种类时,只需让新的图形类继承Shape,并实现draw方法即可。使用方的代码就不需要修改,满足开闭原则。

image.png

6. 迪米特原则

迪米特法则 (Demeter Principle) 又叫最少知道原则,即一个类对自己依赖的类知道的越少越好,核心是降低类之间的耦合。

也就是说,对于被依赖的类不管多么复杂,都尽量将逻辑封装在类的内部。对外除了提供的 public 方法,不对外泄露任何信息。

迪米特法则还有个更简单的定义:只与直接的朋友通信

直接的朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。耦合的方式很多,依赖,关联,组合,聚合等。其中,我们称出现成员变量,方法参数,方法返回值中的类为直接的朋友,而出现在局部变量中的类不是直接的朋友。也就是说,陌生的类最好不要以局部变量的形式出现在类的内部。

栗子.png 举个坏栗子

比如有学院员工类和学校员工类,然后各有一个管理类有可以获取其所有员工,学校员工管理类有方法打印全部员工。

image.png

分析SchoolManager类,发现Employee和CollegeManager都是它的直接朋友(出现在参数和返回值中),但CollegeEmployee不是直接朋友,是以局部变量的形式,违背了迪米特原则。

改进.png 改进

避免依赖CollegeEmployee,封装在CollegeManager中,对外提供public方法即可。

image.png

7. 合成复用原则

合成复用原则 (Composite Reuse Principle) 就是尽量使用合成/聚合的方式,而不是使用继承

三、核心思想

找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起;

针对接口编程,而不是针对实现编程;

为了交互对象之间的松耦合设计而努力。