目录
- 1. 什么是设计模式?
- 2. 设计原则概述
- 3. 设计模式核心思想
- 4. 设计模式分类
1. 什么是设计模式?
设计模式是一套被反复使用、多数人知晓、经过分类编目的、代码设计经验的总结。它是为了可重用代码,让代码更容易的被他人理解并保证代码的可靠性。
就像是我们在做数学题的时候,已知直角三角形两边长,求另一边,我们会直接用勾股定理,而不会去证明为什么勾股定理是成立的。所以,设计模式实际上是“拿来主义”在软件领域的贯彻实践,它是一套现成的工具,拿来即用。
下面来看一下设计模式的设计原则。
2. 设计原则概述
设计原则是设计模式的指导理论,它可以帮助我们规避不良的软件设计。设计模式遵循SOLID原则,SOLID 指代的五个基本原则分别是:
- 单一功能原则(Single Responsibility Principle)
- 开放封闭原则(Opened Closed Principle)
- 里式替换原则(Liskov Substitution Principle)
- 接口隔离原则(Interface Segregation Principle)
- 依赖反转原则(Dependency Inversion Principle)
这五个基本原则看起来挺高大上的,实际上并不是很难。而且JavaScript的设计模式主要围绕单一功能原则和开放封闭原则展开:
- 单一功能原则:官方的说法是“规定每个类都应该有一个单一的功能,并且该功能应该由这个类完全封装起来”。简单来说,可以理解为不要让一个函数/类做太多事情,而应该进行合理的功能拆分,并且每部分都保持独立。
- 开放封闭原则:官方的说法是“软件实体应该是可扩展,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的”。 简单来说,我们设计一个功能时,需要尽可能地区分变化的部分与稳定的部分,进而做到将变与不变分离(尤其是要做到封装变化的部分),达到降低耦合度的目的(在增加需求时,扩展新代码,而非修改已有代码)。
下面我们看要个一个Promise的例子:
function loadImg (src){
let promise = new Promise( (resolve, reject) => {
let img = document.createElement('img')
img.onload = function(){
resolve(img)
}
img.onerror = function(){
reject('加载失败')
}
img.src = src
}
return promise
}
let src = './pic.jpg'
let result = loadImg(src)
result.then( (img) => {
console.log(`width: ${img.width}`)
}).then( (img) => {
console.log(`height: ${img.height}`)
}).catch((error) => {
console.log(error)
})
在这个例子中,我们创建了一个Promise异步图片的加载任务,并且打印图片的宽和高,以及错误的捕获,它符合以下两条原则:
- 单一职责原则:每一个then中值需做好自己的事。
- 开放封闭原则:如果新增需求,就可以继续加then,而基本不用动之前的两个then。
3. 设计模式核心思想
设计模式出现的背景,是软件设计的复杂度日益飙升。软件设计越来越复杂的“罪魁祸首”,就是变化。
这一点相信大家不难理解——如果说我们写一个业务,这个业务不需要更新迭代,初始版本是 1.0,10 年后还是 1.0,不接受任何迭代和优化,那么这个业务几乎可以随便写。反正只要实现功能就行了,完全不需要考虑可维护性、可扩展性。
但在实际开发中,不发生变化的代码可以说是不存在的。我们能做的只有将这个变化造成的影响最小化 —— 将变与不变分离,确保变化的部分灵活、不变的部分稳定。
这个过程,就叫“封装变化”;这样的代码,就是我们所谓的“健壮”的代码,它可以经得起变化的考验。而设计模式出现的意义,就是帮我们写出这样的代码。
4. 设计模式分类
根据上面的设计模式,总共提出了23种设计模式,并按照创建型、行为型、结构型进行划分,如下:
- 工厂模式
- 单例模式
- 原型模式
- 装饰器模式
- 适配器模式
- 代理模式
- 策略模式
- 状态模式
- 观察者模式/发布订阅模式
- 迭代器模式