# JavaScript设计模式小册

本小册从概念到场景再到示例,解析前端常用设计模式,第一步总览设计模式的前传,也就是面向对象概念以及设计原则,然后对每一个设计模式从介绍到UML类图再到场景与示例,最后对设计原则的验证,让各位对设计模式有一个更深入的了解,能够在日常开发中运用。

WARNING

小册以代码为主,所以阅读小册需要有一定的JavaScript基础(ES6)

# 面向对象

# 三要素

  • 继承:子类继承父类
    • 父类是公共的,不仅仅只服务于一个子类
    • 继承可以将公共方法抽离出来,提高复用性,减少冗余
  • 封装:数据的权限和保密(Javascript,甚至Es6本身都没有封装这个概念,但Typescript可实现封装)
    • 关键字(定义属性/方法)
      • public 完全开放
      • protected 对子类开放
      • private 对自己开放
    • 特点
      • 减少耦合,不该暴露的不暴露
      • 利于数据,接口的权限管理
      • Es不支持,我们可以去约定某种形式( _ 开头)去告诉合作者这是private类型
  • 多态:同一接口不同实现
    • Js对于多态的应用极少,因为需要结合Java等语言的接口,重写,重载等功能
    • 未来Ts的大范围普及,多态的功能也会更加显著
    • 特点
      • 保持子类的开放性和灵活性
      • 面向接口编程(Js使用较少)

# Js应用举例

JQuery就是一个class,而${'p'}就是JQuery的一个实例

class JQuery {
    constructor(selector) {
            let slice = Array.prototype.slice
            let dom = slice.call(document.querySelectorAll(selector)) // 获取每一个dom元素
            let len = dom ? dom.length : 0
            for (let i = 0; i < len; i++) {
                this[i] = dom[i]
            }
            this.length = len
            this.selector = selector || ''
        }
        // JQuery自身API
    append(node) {
        // TODO
    }
    addClass(name) {
        // TODO
    }
    html(data) {
            // TODO
        }
        // ...
}

window.$ = function(selector) {
    return new JQuery
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
使用
var $p = $('p')
$p.append(xxx)
1
2
3

# 为何要使用面向对象

  • 面向对象是为了解决系统的可维护性,可扩展性,可重用性
  • 面向对象实现了一种数据的结构化,是为了表述、模拟世间万事
  • 面向对象的意义是将平整的数据进行结构化。对于计算机而已,结构化才是最简单的、
  • 编程应该做到 简单 & 抽象
好处:
当需求单一,或者简单时我们一步一步操作没有问题,并且效率也挺高。可随着需求的更改,功能的增多,发现于鏊面对每一个步骤很麻烦了,这时就开始思索能不能把步骤和功能进行封装。封装时根据不同的功能,进行不同的封装,功能类似的封装在一起。这样结构就清晰了很多。用的时候找到对应的类就可以了。
1
2

# 设计原则

# 何为设计?

  • 按照哪一种思路或者标准来实现功能
  • 功能相同,可以有不同的设计方案来实现
  • 随着需求的增加,设计的作用才能体现出来

# 五大设计原则 (SOLID)

❗ 五大设计原则可以说是设计模式的基础,学好设计模式应该先理解五大设计原则

S - 单一职责原则
        - 一个程序只做好一件事
        - 如果功能过于复杂就拆分开,每个部分保持独立
O - 开放封闭原则
        - 对扩展开放,对修改封闭(重点)
        - 增加需求时,尽量做到扩展新代码,而非修改已有代码
L - 李氏置换原则
        - 子类能覆盖父类
        - 父类能出现的地方子类就能出现
        - 由于Js是弱类型,以及继承使用较少,所以在Js中应用较少
I - 接口独立原则
        - 保持接口的单一独立,功能统一
        - Js中没有接口(TypeScript除外),使用较少
        - 类似于单一职责原则,但更关注于接口
D - 依赖导致原则
        - 面向接口编程,依赖于抽象而不依赖于具体
        - 使用方只关注接口而不关注具体类的实现
        - Js中使用较少(没有接口 & 弱类型)

JavaScript中:S O体现较多 L I D体现较少
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 用 Promise 来说明 S 与 O

// 加载图片
function loadImg(src) {
    var promise = new Promise((resolve,reject) => {
        var img = document.createElement('img')
        img.onload = () => {
            resolve(img)
        }
        img.onerror = () => {
            reject('图片加载失败')
        }
        img.src = src
    })
    return promise
}
var src = '...'
var result = loadImg(src)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
result.then(img => {
    console.log('width:',img.width)
    return img
}).then(img => {
    console.log('height:',img.height)
}).catch( err => {
    // 捕获异常
    console.log(err)
})
1
2
3
4
5
6
7
8
9

观察上面这个例子,我们可以发现

单一职责原则体现在我们每一个then只做一件事,如果上面还想再做第三件事,我们就再加一个then,而不是在第一个或第二个then中多做一件事

开放封闭原则体现在如果我们有新的需求进来,我们不需要去修改第一第二个then,而是直接添加一个then去实现

总结:
单一职责原则:每一个 then 中的逻辑只做好一件事
开放封闭原则:如果新增需求,扩展 then
1
2
3

# 23种设计模式简介

  • 创建型
    • 工厂模式(工厂方法模式,抽象工厂模式,建造者模式)
    • 单例模式
    • 原型模式
  • 结构型
    • 适配器模式
    • 装饰器模式
    • 代理模式
    • 外观模式
    • 桥接模式
    • 组合模式
    • 享元模式
  • 行为型
    • 策略模式
    • 模板方法模式
    • 观察者模式 (Js应用较多)
    • 迭代器模式 (Js应用较多)
    • 职责链模式
    • 命令模式
    • 备忘录模式
    • 状态模式 (Js应用较多)
    • 访问者模式
    • 中介者模式
    • 解释器模式
Last Updated: 12/7/2019, 1:01:22 AM