引言:
灵活运用设计模式,可以提高代码的可维护性,还可提升自身思维能力。以下分析一些前端常用的设计模式,对比优缺点:
设计原则:
- 单一职责原则
- 开放|封闭原则
- 里氏替换原则
- 接口隔离原则
- 依赖倒转原则
1. 单例模式
定义:保证一个类只有一个实例, 一般先判断实例是否存在,如果存在直接返回, 不存在则先创建再返回,这样就可以保证一个类只有一个实例对象
使用场景:确保只有一个实例。比如:登录浮窗、Vue中的axios实例(对axios进行请求拦截和响应拦截,多次调用封装好的axios但是仅设置一次,封装好的axios导出就是一个单例)、全局状态管理 store等
优点:
- 划分命名空间,减少全局变量
- 增强模块性,把代码组织在一个全局变量名下,放在单一位置,便于维护且只会实例化一次
- 简化了代码的调试和维护
缺点:
- 不适用动态扩展对象。
2. 策略模式
定义:要实现某一个功能,有多种方案可以选择。定义策略然后把它们一个个封装起来,并且使它们可以相互转换。
适用场景:根据表单验证策略进行表单验证等。
优点:
- 利用组合、委托、多态等技术和思想,可以有效的避免多重条件选择语句
- 提供了对开放-封闭原则的完美支持,将算法封装在独立的strategy中,使得它们易于切换,理解,易于扩展
- 利用组合和委托来让Context拥有执行算法的能力,这也是继承的一种更轻便的代替方案
缺点:
- 会在程序中增加许多策略类或者策略对象
- 要使用策略模式,必须了解所有的strategy,必须了解各个strategy之间的不同点,这样才能选择一个合适的
3. 工厂模式
定义:工厂模式是指通过一个工厂类来创建其他类的实例。这个模式非常适合那些需要根据不同条件创建不同实例的场景
使用场景:例如jquery的$函数,该函数接收一个选择器字符串作为参数,然后返回与该选择器匹配的一个或多个元素。
优点:
- 创建对象的过程可能很复杂,但我们只需要关心创建结果。
- 构造函数和创建者分离, 符合“开闭原则”
- 一个调用者想创建一个对象,只要知道其名称就可以了。
- 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以
缺点:
- 添加新产品时,需要编写新的具体产品类,一定程度上增加了系统的复杂度
- 考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度
4. 外观模式
定义:外观模式是最常见的设计模式之一,它为子系统中的一组接口提供一个统一的高层接口,使子系统更容易使用。
使用场景:可以使用外观模式来设计兼容不同浏览器的事件绑定的方法以及其他需要统一实现接口的方法或者抽象类。
优点
- 减少系统相互依赖
- 提高灵活性
- 提高了安全性
缺点
- 不符合开闭原则,如果要改东西很麻烦,继承重写都不合适。
5.观察者模式
定义:观察者模式又称发布订阅模式。例如订阅了某个博主的频道,当有内容更新时会收到推送;比如JavaScript中的事件订阅响应机制。当被观察对象状态改变时,通过调用观察者的某个方法将这些变化通知到观察者。
使用场景:如给DOM元素绑定事件的 addEventListener() 方法、还有Vue中的watch 就是依赖于这个模式,在wacth中,被监听的数据充当了发布者,而执行的回调函数充当了订阅者。当数据变化时,发布者会通知所有订阅者执行回调函数,从而实现对数据变化的监听。
优点:
- 支持简单的广播通信,自动通知所有已经订阅过的对象
- 目标对象与观察者之间的抽象耦合关系能单独扩展以及重用
- 增加了灵活性
- 观察者模式所做的工作就是在解耦,让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响到另一边的变化。
缺点:
- 过度使用会导致对象与对象之间的联系弱化,会导致程序难以跟踪维护和理解