├── .gitignore
├── 02-this、new、bind、call、apply
├── 02-01.this new绑定.js
├── 02-02.this 显式绑定 call apply.js
├── 02-03.this 显式绑定 bind.js
├── 02-04.this 显式绑定 忽略的情况.js
├── 02-05.this 隐式绑定.js
├── 02-06.this 隐式绑定 demo2.js
├── 02-07.this 隐式绑定 demo3.js
├── 02-08.this 默认绑定.js
├── 02-09.this 默认绑定 demo2.js
├── 02-10.this 箭头函数.js
├── 02-11.this 小练习.js
└── 02-12.this 小练习 demo2.js
├── 03-闭包与高阶函数
├── 03-01.闭包.js
├── 03-02.备忘模式 es5.js
├── 03-03.备忘模式 es6.js
├── 03-04.高阶函数 filter.js
├── 03-05.柯里化通用实现 es5.js
├── 03-06.柯里化通用实现 es6.js
├── 03-07.反柯里化通用实现 es5.js
└── 03-08.反柯里化通用实现 es6.js
├── 04-ES6相关知识点
├── 04-01.var作用域.js
├── 04-02.let作用域.js
├── 04-03.使用函数参数来缓存var变量的值.js
├── 04-04.变量提升.js
├── 04-05.箭头函数使用call、apply.js
├── 04-06.类的基本用法.js
└── 04-07.函数参数默认值.js
├── 05-封装、继承、多态
├── 05-01.对象继承.js
├── 05-02.原型链 demo1.js
├── 05-03.原型链 demo2.js
├── 05-04.原型链 demo3.js
├── 05-05.构造函数窃取.js
├── 05-06.组合继承.js
├── 05-07.寄生组合式继承.js
├── 05-08.ES6 的 extends 实现继承.js
├── 继承与原型链-原型链继承.png
├── 继承与原型链-对象继承.png
├── 继承与原型链.xml
└── 面向对象三大特性五大原则.xmind
├── 07-单例模式
├── 07-01.game demo1.js
├── 07-02.game demo2 class语法实现.js
├── 07-03.singleton IIFE.js
├── 07-04.singleton IIFE pro1.js
├── 07-05.singleton IIFE pro2.js
├── 07-06.singleton overwrite 构造函数复写方式.js
├── 07-07.singleton 块级作用域方式.js
├── 07-08.singleton 模块模式方式.js
├── 07-09.singleton hungry 饿汉式.js
├── 07-10.singleton lazy 懒汉式.js
├── 07-11.singleton ES6.js
├── 单例模式.png
└── 单例模式.xml
├── 08-工厂模式
├── 08-01.restaurant demo1.js
├── 08-02.restaurant demo2 class.js
├── 08-03.restaurant demo3 class.js
├── 08-04.factory demo1 class.js
├── 工厂模式-demo1.png
├── 工厂模式-概略图.png
└── 工厂模式.xml
├── 09-抽象工厂模式
├── 09-01.restaurant demo1 prototype.js
├── 09-02.restaurant demo2 class.js
├── 09-03.restaurant demo3 class.js
├── 09-04.abstract factory demo1 class.js
├── 09-05.abstract factory demo2 class.js
├── 抽象工厂模式.png
└── 抽象工厂模式.xml
├── 10-建造者模式
├── 10-01.car demo1.js
├── 10-02.car demo2 class.js
├── 10-03.car demo3 chain.js
├── 10-04.builder demo1 class.js
├── 10-05.builder demo2 chain.js
├── 10-06.builder demo1.js
├── 10-07.builder demo2.js
├── 10-08.builder react.js
├── 建造者模式.png
└── 建造者模式.xml
├── 11-代理模式
├── 11-01.superstar demo1.js
├── 11-02.superstar demo2.js
├── 11-03.superstar demo3 Proxy.js
├── 11-04.superstar demo4 Object.defineProperty.js
├── 代理模式.png
├── 代理模式.xml
└── 正向代理与反向代理.png
├── 12-享元模式
├── 12-01.superstar demo1.js
├── 12-02.superstar demo2.js
├── 12-03.superstar demo3.js
├── Nodejs 线程池.png
├── 享元模式.png
├── 享元模式.xml
├── 缓存服务器.png
└── 运行动图.gif
├── 13-适配器模式
├── 13-01.plugAdapter.js
├── 13-02.ajax2axios demo.js
├── 13-03.tree2array demo.js
├── 官网计算属性例子.vue
├── 适配器模式.png
└── 适配器模式.xml
├── 14-装饰者模式
├── 14-01.decoration demo1 es5.js
├── 14-02.decoration demo2 es6.js
├── 14-03.decoration demo3.js
├── 14-04.decoration demo4.html
├── 14-05.decoration demo5.html
├── 14-06.decoration in TypeScript demo1.ts
├── 14-07.decoration in TypeScript demo2.ts
├── 14-08.decoration in TypeScript demo3.ts
├── tsconfig.json
├── 装饰器模式.drawio
└── 装饰器模式.png
├── 15-外观模式
├── 15-01.uav demo1.js
├── 15-02.facade demo1.js
├── 15-03.facade demo2.js
├── 15-04.facade demo3.js
├── 外观模式-无人机模块图.png
├── 外观模式.png
└── 外观模式.xml
├── 16-组合模式
├── 16-01.folder demo1.js
├── 16-02.folder demo2.js
├── 16-03.folder class demo.js
├── 16-04.create element.js
├── 组合模式.png
└── 组合模式.xml
├── 17-桥接模式
├── 17-01.washer demo1.js
├── 17-02.washer class demo2.js
├── 17-03.bag class demo1.js
├── 17-04.operate DOM demo1.js
├── 17-05.operate DOM demo2.js
├── 操作DOM.gif
├── 桥接模式.png
└── 桥接模式.xml
├── 18-发布-订阅模式
├── 18-01.adadis demo1.js
├── 18-02.adadis demo2.js
├── 18-03.adadis demo3.js
├── 18-04.pub-sub IIFE.js
├── 18-05.pub-sub class.js
├── 18-06.pub-sub jquery.js
├── 18-07.pub-sub native.js
├── 发布-订阅模式 概略图.png
├── 发布-订阅模式-adadis.png
└── 发布-订阅模式.xml
├── 19-策略模式
├── 19-01.priceclac.js
├── 19-02.priceclac pro1.js
├── 19-03.priceclac pro1 IIFE.js
├── 19-04.strategy.js
├── 19-05.strategy demo1.js
├── 19-06.ElTableDemo.vue
├── 19-07.ElFormDemo.vue
├── strategyContext.js
├── utils
│ ├── index.js
│ └── validates.js
├── 策略模式.png
└── 策略模式.xml
├── 20-状态模式
├── 20-01.trafficlight demo1.js
├── 20-02.trafficlight demo2.js
├── 20-03.trafficlight demo3.js
├── 20-04.trafficlight demo4.js
├── 状态模式-红绿灯.gif
├── 状态模式-红绿灯.png
└── 状态模式.xml
├── 21-模板方法模式
├── 21-01.coffee demo1.js
├── 21-02.coffee demo2 class.js
├── 21-03.coffee demo3 param.js
├── 21-04.coffee demo4 class param.js
├── 21-05.template class.js
├── 21-06.template class param.js
├── 21-06.template higher-order function.js
├── 模板方法模式-咖啡厅.png
├── 模板方法模式-模板方法模式.png
└── 模板方法模式.xml
├── 22-迭代器模式
├── 22-01.iterator demo1.js
├── 22-02.iterator demo2.js
├── 22-03.iterator demo3.js
└── 22-04.iterator demo4.js
├── 23-命令模式
├── 23-01.command demo1.js
├── 23-02.command demo2.js
├── 23-03.command demo3.js
├── 23-04.command demo4.js
├── 23-05.command demo5.js
├── 状态模式-小游戏1.gif
└── 状态模式-小游戏2.gif
├── 24-职责链模式
├── 24-01.leader demo1.js
├── 24-02.leader demo2.js
├── 24-03.leader demo3.js
├── 24-04.leader demo4.js
├── 24-05.leader demo5 es6.js
├── 24-06.leader demo6.js
├── 24-07.leader demo7 es6.js
├── 事件冒泡.png
└── 事件冒泡.xml
├── 25-中介者模式
├── 25-01.dating demo1 class.js
├── 25-02.dating demo2.js
├── 25-03.dating demo3.js
├── 25-04.dating demo4.js
├── 中介者模式.png
└── 中介者模式.xml
├── 26-MVC、MVP、MVVM
├── MVC.png
├── MVC1.png
├── MVC2.png
├── MVC、MVP、MVVM.xml
├── MVP.png
├── MVP1.png
└── MVVM.png
├── 27-模块模式
├── 27-01.namespace demo1.js
├── 27-02.module demo1.js
├── 27-03.module demo2.js
├── 27-04.module es6 export demo1.js
├── 27-05.module es6 import demo1.js
├── 27-06.module es6 export default demo2.js
└── 27-07.module es6 import default demo2.js
├── 28-链模式
├── 28-01.chain demo1.js
├── 28-02.chain demo2.js
├── 28-03.chain demo3.js
├── 28-04.dom demo1.js
└── 28-05.dom demo2.js
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 |
--------------------------------------------------------------------------------
/02-this、new、bind、call、apply/02-01.this new绑定.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: this
3 | * 作者: SHERlocked93
4 | * 功能: 通过 new 调用的函数中的 this
5 | */
6 |
7 | function Foo() {
8 | console.log(this)
9 | }
10 |
11 | var bar = new Foo()
12 |
13 | // 输出: Foo 实例
14 |
--------------------------------------------------------------------------------
/02-this、new、bind、call、apply/02-02.this 显式绑定 call apply.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: this
3 | * 作者: SHERlocked93
4 | * 功能: 显式绑定 call apply
5 | */
6 |
7 | function foo(name, price) {
8 | this.name = name
9 | this.price = price
10 | }
11 |
12 | function Food(category, name, price) {
13 | foo.call(this, name, price) // call 方式调用
14 | // foo.apply(this, [name, price]) // apply 方式调用
15 | this.category = category
16 | }
17 |
18 | new Food('吃的', '汉堡', '5块钱')
19 |
20 | // 浏览器中输出: {name: "汉堡", price: "5块钱", category: "吃的"}
21 |
--------------------------------------------------------------------------------
/02-this、new、bind、call、apply/02-03.this 显式绑定 bind.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: this
3 | * 作者: SHERlocked93
4 | * 功能: 显式绑定 bind
5 | */
6 |
7 | var food = {
8 | name: '汉堡',
9 | price: '5块钱',
10 | getPrice: function(place) {
11 | console.log(place + this.price)
12 | }
13 | }
14 |
15 | food.getPrice('KFC ') // 浏览器中输出: "KFC 5块钱"
16 |
17 | var getPrice1 = food.getPrice.bind({ name: '鸡腿', price: '7块钱' }, '肯打鸡 ')
18 | getPrice1() // 浏览器中输出: "肯打鸡 7块钱"
19 |
20 | Function.prototype.bind = Function.prototype.bind || function(...rest1) {
21 | const self = this
22 | const context = rest1.shift()
23 | return function(...rest2) {
24 | return self.apply(context, [...rest1, ...rest2])
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/02-this、new、bind、call、apply/02-04.this 显式绑定 忽略的情况.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: this
3 | * 作者: SHERlocked93
4 | * 功能: 显式绑定 call apply
5 | */
6 |
7 | var a = 'hello'
8 |
9 | function foo() {
10 | console.log(this.a)
11 | }
12 |
13 | foo.call(null) // 浏览器中输出: "hello"
14 |
--------------------------------------------------------------------------------
/02-this、new、bind、call、apply/02-05.this 隐式绑定.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: this
3 | * 作者: SHERlocked93
4 | * 功能: 隐式绑定
5 | */
6 |
7 | var a = 'hello'
8 |
9 | var obj = {
10 | a: 'world',
11 | foo: function() {
12 | console.log(this.a)
13 | }
14 | }
15 |
16 | obj.foo()
17 |
18 | // 浏览器中输出: hello
19 |
--------------------------------------------------------------------------------
/02-this、new、bind、call、apply/02-06.this 隐式绑定 demo2.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: this
3 | * 作者: SHERlocked93
4 | * 功能: 隐式绑定
5 | */
6 |
7 | var a = 'hello'
8 |
9 | var obj = {
10 | a: 'world',
11 | b:{
12 | a:'China',
13 | foo: function() {
14 | console.log(this.a)
15 | }
16 | }
17 | }
18 |
19 | obj.b.foo()
20 |
21 | // 浏览器中输出: China
22 |
--------------------------------------------------------------------------------
/02-this、new、bind、call、apply/02-07.this 隐式绑定 demo3.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: this
3 | * 作者: SHERlocked93
4 | * 功能: 隐式绑定 方法作为回调函数的场景
5 | */
6 |
7 | var a = 'hello'
8 |
9 | var obj = {
10 | a: 'world',
11 | foo: function() {
12 | console.log(this.a)
13 | }
14 | }
15 |
16 | function func(fn) {
17 | fn()
18 | }
19 |
20 | func(obj.foo) // 浏览器中输出: 'hello'
21 |
--------------------------------------------------------------------------------
/02-this、new、bind、call、apply/02-08.this 默认绑定.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: this
3 | * 作者: SHERlocked93
4 | * 功能: 独立函数调用方式
5 | */
6 |
7 | var a = 'hello'
8 |
9 | function foo() {
10 | var a = 'world'
11 | console.log(this.a)
12 | console.log(this)
13 | }
14 |
15 | foo()
16 | // 浏览器中输出: 'hello'
17 | // 浏览器中输出: Window 对象
18 |
--------------------------------------------------------------------------------
/02-this、new、bind、call、apply/02-09.this 默认绑定 demo2.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: this
3 | * 作者: SHERlocked93
4 | * 功能: 独立函数调用方式
5 | */
6 |
7 | var a = 'hello'
8 |
9 | var obj = {
10 | a: 'world',
11 | foo: function() {
12 | console.log(this.a)
13 | }
14 | }
15 |
16 | var bar = obj.foo
17 |
18 | bar()
19 |
20 | // 浏览器中输出: 'hello'
21 |
--------------------------------------------------------------------------------
/02-this、new、bind、call、apply/02-10.this 箭头函数.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: this
3 | * 作者: SHERlocked93
4 | * 功能: 箭头函数中的this
5 | */
6 |
7 | var a = 'hello'
8 |
9 | var obj = {
10 | a: 'world',
11 | foo: () => {
12 | console.log(this.a)
13 | }
14 | }
15 |
16 | obj.foo()
17 |
18 | // 浏览器中输出: 'hello'
19 |
--------------------------------------------------------------------------------
/02-this、new、bind、call、apply/02-11.this 小练习.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: this
3 | * 作者: SHERlocked93
4 | * 功能: 一个小练习
5 | */
6 |
7 | var a = 20
8 |
9 | var obj = {
10 | a: 40,
11 | foo:() => {
12 | console.log(this.a)
13 |
14 | function func() {
15 | this.a = 60
16 | console.log(this.a)
17 | }
18 |
19 | func.prototype.a = 50
20 | return func
21 | }
22 | }
23 |
24 | var bar = obj.foo() // 浏览器中输出: 20
25 | bar() // 浏览器中输出: 60
26 | new bar() // 浏览器中输出: 60
27 |
--------------------------------------------------------------------------------
/02-this、new、bind、call、apply/02-12.this 小练习 demo2.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: this
3 | * 作者: SHERlocked93
4 | * 功能: 一个小练习
5 | */
6 |
7 | var a = 20
8 |
9 | var obj = {
10 | a: 40,
11 | foo: function() {
12 | console.log(this.a)
13 |
14 | function func() {
15 | this.a = 60
16 | console.log(this.a)
17 | }
18 |
19 | func.prototype.a = 50
20 | return func
21 | }
22 | }
23 |
24 | var bar = obj.foo() // 浏览器中输出: 40
25 | bar() // 浏览器中输出: 60
26 | new bar() // 浏览器中输出: 60
27 |
--------------------------------------------------------------------------------
/03-闭包与高阶函数/03-01.闭包.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 闭包与高阶函数
3 | * 作者: SHERlocked93
4 | * 功能: 闭包
5 | */
6 |
7 |
8 | function foo() {
9 | var a = 2
10 |
11 | function bar() {
12 | console.log(a)
13 | }
14 |
15 | return bar
16 | }
17 |
18 | var baz = foo()
19 |
20 | baz()
21 |
22 | // 输出: 2
23 |
--------------------------------------------------------------------------------
/03-闭包与高阶函数/03-02.备忘模式 es5.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 闭包与高阶函数
3 | * 作者: SHERlocked93
4 | * 功能: 备忘模式
5 | */
6 |
7 |
8 | /**
9 | * 备忘函数
10 | * @param fn
11 | * @returns {function(): *}
12 | */
13 | function memorize(fn) {
14 | var cache = {}
15 | return function() {
16 | var args = Array.prototype.slice.call(arguments)
17 | var key = JSON.stringify(args)
18 | return cache[key] || (cache[key] = fn.apply(fn, args))
19 | }
20 | }
21 |
22 | /* 复杂计算函数 */
23 | function add(a) {
24 | return a + 1
25 | }
26 |
27 | var adder = memorize(add)
28 |
29 | adder(1) // 输出: 2 当前: cache: { '[1]': 2 }
30 | adder(1) // 输出: 2 当前: cache: { '[1]': 2 }
31 | adder(2) // 输出: 3 当前: cache: { '[1]': 2, '[2]': 3 }
32 |
--------------------------------------------------------------------------------
/03-闭包与高阶函数/03-03.备忘模式 es6.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 闭包与高阶函数
3 | * 作者: SHERlocked93
4 | * 功能: 备忘模式
5 | */
6 |
7 |
8 | /**
9 | * 备忘函数
10 | * @param fn
11 | * @returns {function(): *}
12 | */
13 | function memorize(fn) {
14 | const cache = {}
15 | return function(...args) {
16 | const key = JSON.stringify(args)
17 | return cache[key] || (cache[key] = fn.apply(fn, args))
18 | }
19 | }
20 |
21 | /* 复杂计算函数 */
22 | function add(a) {
23 | return a + 1
24 | }
25 |
26 | const adder = memorize(add)
27 |
28 | adder(1) // 输出: 2 当前: cache: { '[1]': 2 }
29 | adder(1) // 输出: 2 当前: cache: { '[1]': 2 }
30 | adder(2) // 输出: 3 当前: cache: { '[1]': 2, '[2]': 3 }
31 |
--------------------------------------------------------------------------------
/03-闭包与高阶函数/03-04.高阶函数 filter.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 闭包与高阶函数
3 | * 作者: SHERlocked93
4 | * 功能: 高阶函数 Array.prototype.filter()
5 | */
6 |
7 |
8 | var words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present']
9 |
10 | var result = words.filter(function(word) {
11 | return word.length > 6
12 | })
13 |
14 | console.log(result)
15 |
16 |
17 | // 输出: ["exuberant", "destruction", "present"]
18 |
--------------------------------------------------------------------------------
/03-闭包与高阶函数/03-05.柯里化通用实现 es5.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 闭包与高阶函数
3 | * 作者: SHERlocked93
4 | * 功能: 柯里化通用实现 es5方式
5 | */
6 |
7 |
8 | function currying(fn) {
9 | var rest1 = Array.prototype.slice.call(arguments)
10 | rest1.shift()
11 | return function() {
12 | var rest2 = Array.prototype.slice.call(arguments)
13 | return fn.apply(null, rest1.concat(rest2))
14 | }
15 | }
16 |
17 | function sayHello(name, age, fruit) {
18 | console.log(console.log(`我叫 ${ name },我 ${ age } 岁了, 我喜欢吃 ${ fruit }`))
19 | }
20 |
21 | var curryingShowMsg1 = currying(sayHello, '小明')
22 | curryingShowMsg1(22, '苹果') // 输出: 我叫 小明,我 22 岁了, 我喜欢吃 苹果
23 |
24 | var curryingShowMsg2 = currying(sayHello, '小衰', 20)
25 | curryingShowMsg2('西瓜') // 输出: 我叫 小衰,我 20 岁了, 我喜欢吃 西瓜
26 |
--------------------------------------------------------------------------------
/03-闭包与高阶函数/03-06.柯里化通用实现 es6.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 闭包与高阶函数
3 | * 作者: SHERlocked93
4 | * 功能: 柯里化通用实现 es6方式
5 | */
6 |
7 |
8 | function currying(fn, ...rest1) {
9 | return function(...rest2) {
10 | return fn.apply(null, rest1.concat(rest2))
11 | }
12 | }
13 |
14 | function sayHello(name, age, fruit) {
15 | console.log(console.log(`我叫 ${ name },我 ${ age } 岁了, 我喜欢吃 ${ fruit }`))
16 | }
17 |
18 | var curryingShowMsg1 = currying(sayHello, '小明')
19 | curryingShowMsg1(22, '苹果') // 输出: 我叫 小明,我 22 岁了, 我喜欢吃 苹果
20 |
21 | var curryingShowMsg2 = currying(sayHello, '小衰', 20)
22 | curryingShowMsg2('西瓜') // 输出: 我叫 小衰,我 20 岁了, 我喜欢吃 西瓜
23 |
--------------------------------------------------------------------------------
/03-闭包与高阶函数/03-07.反柯里化通用实现 es5.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 闭包与高阶函数
3 | * 作者: SHERlocked93
4 | * 功能: 反柯里化通用实现 es5方式
5 | */
6 |
7 |
8 | function unCurrying(fn) {
9 | return function(tar) {
10 | var rest = Array.prototype.slice.call(arguments)
11 | rest.shift()
12 | return fn.apply(tar, rest)
13 | }
14 | }
15 |
16 | var push = unCurrying(Array.prototype.push)
17 |
18 | function execPush() {
19 | push(arguments, 4)
20 | console.log(arguments)
21 | }
22 |
23 | execPush(1, 2, 3)
24 |
25 | // 输出: [1, 2, 3, 4]
26 |
--------------------------------------------------------------------------------
/03-闭包与高阶函数/03-08.反柯里化通用实现 es6.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 闭包与高阶函数
3 | * 作者: SHERlocked93
4 | * 功能: 反柯里化通用实现 es6方式
5 | */
6 |
7 |
8 | function unCurrying(fn) {
9 | return function(tar, ...argu) {
10 | return fn.apply(tar, argu)
11 | }
12 | }
13 |
14 | var push = unCurrying(Array.prototype.push)
15 |
16 | function execPush() {
17 | push(arguments, 4)
18 | console.log(arguments)
19 | }
20 |
21 | execPush(1, 2, 3)
22 |
23 | // 输出: [1, 2, 3, 4]
24 |
--------------------------------------------------------------------------------
/04-ES6相关知识点/04-01.var作用域.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: ES6 相关知识点
3 | * 作者: SHERlocked93
4 | * 功能: var命令只有函数作用域
5 | */
6 |
7 |
8 | var a = []
9 |
10 | for (var i = 0; i < 4; i++) {
11 | a[i] = function() {
12 | console.log(i)
13 | }
14 | }
15 |
16 | a[2]() // 输出: 4
17 |
--------------------------------------------------------------------------------
/04-ES6相关知识点/04-02.let作用域.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: ES6 相关知识点
3 | * 作者: SHERlocked93
4 | * 功能: let命令声明的变量具有块级作用域
5 | */
6 |
7 |
8 | var a = []
9 |
10 | for (let i = 0; i < 4; i++) {
11 | a[i] = function() {
12 | console.log(i)
13 | }
14 | }
15 |
16 | a[2]() // 输出: 2
17 |
--------------------------------------------------------------------------------
/04-ES6相关知识点/04-03.使用函数参数来缓存var变量的值.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: ES6 相关知识点
3 | * 作者: SHERlocked93
4 | * 功能: 使用函数参数来缓存var变量的值
5 | */
6 |
7 |
8 | var a = []
9 |
10 | for (var i = 0; i < 4; i++) {
11 | (function(j) {
12 | a[i] = function(j) {
13 | console.log(j)
14 | }
15 | })(i)
16 | }
17 |
18 | a[2]() // 输出: 4
19 |
--------------------------------------------------------------------------------
/04-ES6相关知识点/04-04.变量提升.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: ES6 相关知识点
3 | * 作者: SHERlocked93
4 | * 功能: 变量提升
5 | */
6 |
7 | // var 命令存在变量提升
8 | console.log(a) // undefined
9 | var a = 1
10 | console.log(a) // 1
11 |
12 | // let、const 命令不存在变量提升
13 | console.log(b) // 报错 ReferenceError: b is not defined
14 | let b = 2
15 |
--------------------------------------------------------------------------------
/04-ES6相关知识点/04-05.箭头函数使用call、apply.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: ES6 相关知识点
3 | * 作者: SHERlocked93
4 | * 功能: 箭头函数使用 call apply
5 | */
6 |
7 | this.param = 1
8 |
9 | const func1 = () => console.log(this.param)
10 | const func2 = function() {
11 | console.log(this.param)
12 | }
13 | func1.apply({ param: 2 }) // 输出: 1
14 | func2.apply({ param: 2 }) // 输出: 2
15 |
--------------------------------------------------------------------------------
/04-ES6相关知识点/04-06.类的基本用法.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: ES6 相关知识点
3 | * 作者: SHERlocked93
4 | * 功能: 类的基本用法
5 | */
6 |
7 | class Foo {
8 | constructor() {
9 | this.kind = 'foo'
10 | }
11 |
12 | static staticMethod() {
13 | console.log('静态方法')
14 | }
15 |
16 | doThis() {
17 | console.log(`实例方法 kind:${ this.kind }`)
18 | }
19 | }
20 |
21 | class Bar extends Foo {
22 | constructor() {
23 | super()
24 | this.type = 'bar'
25 | }
26 |
27 | doThat() {
28 | console.log(`实例方法 type:${ this.type } kind:${ this.kind }`)
29 | }
30 | }
31 |
32 | const bar = new Bar()
33 | bar.doThat() // 实例方法 type:bar kind:foo
34 |
--------------------------------------------------------------------------------
/04-ES6相关知识点/04-07.函数参数默认值.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: ES6 相关知识点
3 | * 作者: SHERlocked93
4 | * 功能: 参数默认值
5 | */
6 |
7 | function log(x, y = 'World') {
8 | console.log(x, y)
9 | }
10 |
11 | log('Hello') // Hello World
12 | log('Hello', undefined) // Hello World
13 | log('Hello', 'China') // Hello China
14 | log(undefined, 'China') // undefined China
15 | // log(, 'China') // 报错
16 | log('Hello', '') // Hello
17 | log('Hello', null) // Hello null
18 |
19 |
--------------------------------------------------------------------------------
/05-封装、继承、多态/05-01.对象继承.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-06-02
3 | * 作者: SHERlocked93
4 | * 功能: 对象继承
5 | */
6 |
7 |
8 | var rectangle = {
9 | sizeType: '四边形',
10 | getSize: function() {
11 | console.log(this.sizeType)
12 | }
13 | }
14 |
15 | var square = Object.create(rectangle, {
16 | sizeType: { value: '正方形' }
17 | })
18 |
19 | rectangle.getSize() // "四方形"
20 | square.getSize() // "正方形"
21 |
22 | console.log(rectangle.hasOwnProperty('getSize')) // true
23 | console.log(rectangle.isPrototypeOf(square)) // true
24 | console.log(square.hasOwnProperty('getSize')) // false
25 | console.log('getSize' in square) // true
26 |
27 | console.log(square.__proto__ === rectangle) // true
28 | console.log(square.__proto__.__proto__ === Object.prototype) // true
29 |
--------------------------------------------------------------------------------
/05-封装、继承、多态/05-02.原型链 demo1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-06-02
3 | * 作者: SHERlocked93
4 | * 功能: 构造函数继承
5 | */
6 |
7 |
8 | // 构造函数
9 | function YourConstructor() {}
10 |
11 | // JavaScript 引擎在背后做的:
12 | YourConstructor.prototype = Object.create(Object.prototype, {
13 | constructor: {
14 | configurable: true,
15 | enumerable: true,
16 | value: YourConstructor,
17 | writable: true
18 | }
19 | })
20 |
21 | console.log(YourConstructor.prototype.__proto__ === Object.prototype) // true
22 |
--------------------------------------------------------------------------------
/05-封装、继承、多态/05-03.原型链 demo2.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-06-02
3 | * 作者: SHERlocked93
4 | * 功能: 构造函数继承
5 | */
6 |
7 | /* 四边形 */
8 | function Rectangle(length, width) {
9 | this.length = length // 长
10 | this.width = width // 宽
11 | }
12 |
13 | /* 获取面积 */
14 | Rectangle.prototype.getArea = function() {
15 | return this.length * this.width
16 | }
17 |
18 | /* 获取尺寸信息 */
19 | Rectangle.prototype.getSize = function() {
20 | console.log(`Rectangle: ${ this.length }x${ this.width },面积: ${ this.getArea() }`)
21 | }
22 |
23 | /* 正方形 */
24 | function Square(size) {
25 | this.length = size
26 | this.width = size
27 | }
28 |
29 | Square.prototype = new Rectangle()
30 | Square.prototype.constructor = Square
31 |
32 | Square.prototype.getSize = function() {
33 | console.log(`Square: ${ this.length }x${ this.width },面积: ${ this.getArea() }`)
34 | }
35 |
36 | var rect = new Rectangle(5, 10)
37 | var squa = new Square(6)
38 |
39 | rect.getSize() // Rectangle: 5x10,面积: 50
40 | squa.getSize() // Square: 6x6,面积: 36
41 |
42 | console.log(rect instanceof Rectangle) // true
43 | console.log(rect instanceof Square) // false
44 | console.log(rect instanceof Object) // true
45 | console.log(squa instanceof Rectangle) // true
46 | console.log(squa instanceof Square) // true
47 | console.log(squa instanceof Object) // true
48 |
--------------------------------------------------------------------------------
/05-封装、继承、多态/05-04.原型链 demo3.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-06-02
3 | * 作者: SHERlocked93
4 | * 功能: 构造函数继承
5 | */
6 |
7 | /* 四边形 */
8 | function Rectangle(...sizes) {
9 | this.sizes = sizes || []
10 | }
11 |
12 | /* 正方形 */
13 | function Square() {}
14 |
15 | Square.prototype = new Rectangle(1, 2)
16 |
17 | var squa1 = new Square() // sizes: [1, 2]
18 |
19 | squa1.sizes.push(3)
20 |
21 | console.log(squa1.sizes) // sizes: [1, 2, 3]
22 |
23 | var squa2 = new Square()
24 |
25 | console.log(squa2.sizes) // sizes: [1, 2, 3] 应该是 [1, 2]
26 |
--------------------------------------------------------------------------------
/05-封装、继承、多态/05-05.构造函数窃取.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-06-02
3 | * 作者: SHERlocked93
4 | * 功能: 构造函数窃取
5 | */
6 |
7 | function getArea() {
8 | return this.length * this.width
9 | }
10 |
11 | /* 四边形 */
12 | function Rectangle(length, width) {
13 | this.length = length
14 | this.width = width
15 | }
16 |
17 | /* 获取面积 */
18 | Rectangle.prototype.getArea = getArea
19 |
20 | /* 获取尺寸信息 */
21 | Rectangle.prototype.getSize = function() {
22 | console.log(`Rectangle: ${ this.length }x${ this.width },面积: ${ this.getArea() }`)
23 | }
24 |
25 | /* 正方形 */
26 | function Square(size) {
27 | Rectangle.call(this, size, size)
28 |
29 | this.getArea = getArea
30 |
31 | this.getSize = function() {
32 | console.log(`Square: ${ this.length }x${ this.width },面积: ${ this.getArea() }`)
33 | }
34 | }
35 |
36 | var rect = new Rectangle(5, 10)
37 | var squa = new Square(6)
38 |
39 | rect.getSize() // Rectangle: 5x10,面积: 50
40 | squa.getSize() // Square: 6x6,面积: 36
41 |
--------------------------------------------------------------------------------
/05-封装、继承、多态/05-06.组合继承.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-06-02
3 | * 作者: SHERlocked93
4 | * 功能: 组合继承
5 | */
6 |
7 | /* 四边形 */
8 | function Rectangle(length, width) {
9 | this.length = length
10 | this.width = width
11 | this.color = 'red'
12 | }
13 |
14 | /* 获取面积 */
15 | Rectangle.prototype.getArea = function() {
16 | return this.length * this.width
17 | }
18 |
19 | /* 获取尺寸信息 */
20 | Rectangle.prototype.getSize = function() {
21 | console.log(`Rectangle: ${ this.length }x${ this.width },面积: ${ this.getArea() }`)
22 | }
23 |
24 | /* 正方形 */
25 | function Square(size) {
26 | Rectangle.call(this, size, size) // 第一次调用 Rectangle 函数
27 | this.color = 'blue'
28 | }
29 |
30 | Square.prototype = new Rectangle() // 第二次调用 Rectangle 函数
31 | Square.prototype.constructor = Square
32 |
33 | Square.prototype.getSize = function() {
34 | console.log(`Square: ${ this.length }x${ this.width },面积: ${ this.getArea() }`)
35 | }
36 |
37 | var rect = new Rectangle(5, 10)
38 | var squa = new Square(6)
39 |
40 | rect.getSize() // Rectangle: 5x10,面积: 50
41 | squa.getSize() // Square: 6x6,面积: 36
42 |
--------------------------------------------------------------------------------
/05-封装、继承、多态/05-07.寄生组合式继承.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-06-02
3 | * 作者: SHERlocked93
4 | * 功能: 寄生组合式继承
5 | */
6 |
7 | /* 实现继承逻辑 */
8 | function inheritPrototype(sub, sup) {
9 | var prototype = Object.create(sup.prototype)
10 | prototype.constructor = sub
11 | sub.prototype = prototype
12 | }
13 |
14 | /* 四边形 */
15 | function Rectangle(length, width) {
16 | this.length = length
17 | this.width = width
18 | this.color = 'red'
19 | }
20 |
21 | /* 获取面积 */
22 | Rectangle.prototype.getArea = function() {
23 | return this.length * this.width
24 | }
25 |
26 | /* 获取尺寸信息 */
27 | Rectangle.prototype.getSize = function() {
28 | console.log(`Rectangle: ${ this.length }x${ this.width },面积: ${ this.getArea() }`)
29 | }
30 |
31 | /* 正方形 */
32 | function Square(size) {
33 | Rectangle.call(this, size, size) // 第一次调用 Rectangle 函数
34 | this.color = 'blue'
35 | }
36 |
37 | // 实现继承
38 | inheritPrototype(Square, Rectangle)
39 |
40 | Square.prototype.getSize = function() {
41 | console.log(`Square: ${ this.length }x${ this.width },面积: ${ this.getArea() }`)
42 | }
43 |
44 | var rect = new Rectangle(5, 10)
45 | var squa = new Square(6)
46 |
47 | rect.getSize() // Rectangle: 5x10,面积: 50
48 | squa.getSize() // Square: 6x6,面积: 36
49 |
--------------------------------------------------------------------------------
/05-封装、继承、多态/05-08.ES6 的 extends 实现继承.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-06-02
3 | * 作者: SHERlocked93
4 | * 功能: 组合继承
5 | */
6 |
7 | /* 四边形 */
8 | class Rectangle {
9 | constructor(length, width) {
10 | this.length = length
11 | this.width = width
12 | this.color = 'red'
13 | }
14 |
15 | /* 获取面积 */
16 | getArea() {
17 | return this.length * this.width
18 | }
19 |
20 | /* 获取尺寸信息 */
21 | getSize() {
22 | console.log(`Rectangle: ${ this.length }x${ this.width },面积: ${ this.getArea() }`)
23 | }
24 | }
25 |
26 | /* 正方形 */
27 | class Square extends Rectangle {
28 | constructor(size) {
29 | super(size, size)
30 | this.color = 'blue'
31 | }
32 |
33 | getSize() {
34 | console.log(`Square: ${ this.length }x${ this.width },面积: ${ this.getArea() }`)
35 | }
36 | }
37 |
38 |
39 | var rect = new Rectangle(5, 10)
40 | var squa = new Square(6)
41 |
42 | rect.getSize() // Rectangle: 5x10,面积: 50
43 | squa.getSize() // Square: 6x6,面积: 36
44 |
45 |
--------------------------------------------------------------------------------
/05-封装、继承、多态/继承与原型链-原型链继承.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/05-封装、继承、多态/继承与原型链-原型链继承.png
--------------------------------------------------------------------------------
/05-封装、继承、多态/继承与原型链-对象继承.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/05-封装、继承、多态/继承与原型链-对象继承.png
--------------------------------------------------------------------------------
/05-封装、继承、多态/继承与原型链.xml:
--------------------------------------------------------------------------------
1 | 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
--------------------------------------------------------------------------------
/05-封装、继承、多态/面向对象三大特性五大原则.xmind:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/05-封装、继承、多态/面向对象三大特性五大原则.xmind
--------------------------------------------------------------------------------
/07-单例模式/07-01.game demo1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 单例模式
3 | * 作者: SHERlocked93
4 | * 功能: 经营游戏例子
5 | */
6 |
7 | function ManageGame() {
8 | if (ManageGame._schedule) { // 判断是否已经有单例了
9 | return ManageGame._schedule
10 | }
11 | ManageGame._schedule = this
12 | }
13 |
14 | ManageGame.getInstance = function() {
15 | if (ManageGame._schedule) { // 判断是否已经有单例了
16 | return ManageGame._schedule
17 | }
18 | return ManageGame._schedule = new ManageGame()
19 | }
20 |
21 | const schedule1 = new ManageGame()
22 | const schedule2 = ManageGame.getInstance()
23 |
24 | console.log(schedule1 === schedule2)
25 |
26 | // 输出: true
27 |
--------------------------------------------------------------------------------
/07-单例模式/07-02.game demo2 class语法实现.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 单例模式
3 | * 作者: SHERlocked93
4 | * 功能: 经营游戏例子
5 | */
6 |
7 | class ManageGame {
8 | static _schedule = null
9 |
10 | static getInstance() {
11 | if (ManageGame._schedule) { // 判断是否已经有单例了
12 | return ManageGame._schedule
13 | }
14 | return ManageGame._schedule = new ManageGame()
15 | }
16 |
17 | constructor() {
18 | if (ManageGame._schedule) { // 判断是否已经有单例了
19 | return ManageGame._schedule
20 | }
21 | ManageGame._schedule = this
22 | }
23 | }
24 |
25 | const schedule1 = new ManageGame()
26 | const schedule2 = ManageGame.getInstance()
27 |
28 | console.log(schedule1 === schedule2)
29 |
30 | // 输出: true
31 |
--------------------------------------------------------------------------------
/07-单例模式/07-03.singleton IIFE.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 单例模式
3 | * 作者: SHERlocked93
4 | * 功能: IIFE 方式创建单例
5 | */
6 |
7 | const Singleton = (function() {
8 | let _instance = null // 存储单例
9 |
10 | const Singleton = function() {
11 | if (_instance) return _instance // 判断是否已有单例
12 | _instance = this
13 | this.init() // 初始化操作
14 | return _instance
15 | }
16 |
17 | Singleton.prototype.init = function() {
18 | this.foo = 'Singleton Pattern'
19 | }
20 |
21 | return Singleton
22 | })()
23 |
24 | const visitor1 = new Singleton()
25 | const visitor2 = new Singleton()
26 |
27 | console.log(visitor1 === visitor2)
28 |
29 | // 输出: true
30 |
--------------------------------------------------------------------------------
/07-单例模式/07-04.singleton IIFE pro1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 单例模式
3 | * 作者: SHERlocked93
4 | * 功能: IIFE 方式创建单例,增加 getInstance 方法
5 | */
6 |
7 | const Singleton = (function() {
8 | let _instance = null // 存储单例
9 |
10 | const Singleton = function() {
11 | if (_instance) return _instance // 判断是否已有单例
12 | _instance = this
13 | this.init() // 初始化操作
14 | return _instance
15 | }
16 |
17 | Singleton.prototype.init = function() {
18 | this.foo = 'Singleton Pattern'
19 | }
20 |
21 | Singleton.getInstance = function(bar) {
22 | if (_instance) return _instance
23 | _instance = new Singleton(bar)
24 | return _instance
25 | }
26 |
27 | return Singleton
28 | })()
29 |
30 | const visitor1 = new Singleton()
31 | const visitor2 = new Singleton() // 既可以 new 获取单例
32 | const visitor3 = Singleton.getInstance() // 也可以 getInstance 获取单例
33 |
34 | console.log(visitor1 === visitor2)
35 | console.log(visitor1 === visitor3)
36 |
37 | // 输出: true
38 | // 输出: true
39 |
--------------------------------------------------------------------------------
/07-单例模式/07-05.singleton IIFE pro2.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 单例模式
3 | * 作者: SHERlocked93
4 | * 功能: IIFE 改进 将单例模式的创建逻辑和业务逻辑拆开
5 | */
6 |
7 | /* 功能类 */
8 | class FuncClass {
9 | constructor(bar) {
10 | this.bar = bar
11 | }
12 |
13 | init() {
14 | this.foo = 'Singleton Pattern'
15 | }
16 | }
17 |
18 | /* 单例模式的赋能类 */
19 | const Singleton = (function() {
20 | let _instance = null // 存储单例
21 |
22 | const ProxySingleton = function(bar) {
23 | if (_instance) return _instance // 判断是否已有单例
24 | _instance = new FuncClass(bar)
25 | return _instance
26 | }
27 |
28 | ProxySingleton.getInstance = function(bar) {
29 | if (_instance) return _instance
30 | _instance = new Singleton(bar)
31 | return _instance
32 | }
33 |
34 | return ProxySingleton
35 | })()
36 |
37 | const visitor1 = new Singleton('单例1')
38 | const visitor2 = new Singleton('单例2')
39 | const visitor3 = Singleton.getInstance()
40 |
41 | console.log(visitor1 === visitor2)
42 | console.log(visitor1 === visitor3)
43 |
44 | // 输出: true
45 | // 输出: true
46 |
--------------------------------------------------------------------------------
/07-单例模式/07-06.singleton overwrite 构造函数复写方式.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 单例模式
3 | * 作者: SHERlocked93
4 | * 功能: 构造函数复写方式 这种方式比较少见,可读性也不好,尽量不要使用在项目中,仅作为视野扩展
5 | */
6 |
7 | function Singleton() {
8 | const _instance = this // 存储单例
9 | init() // 初始化操作
10 |
11 | Singleton = function() {
12 | return _instance
13 | }
14 |
15 | function init() {
16 | _instance.foo = 'Singleton Pattern'
17 | }
18 | }
19 |
20 | const visitor1 = new Singleton()
21 | const visitor2 = new Singleton()
22 |
23 | console.log(visitor1 === visitor2)
24 |
25 | // 输出: true
26 |
--------------------------------------------------------------------------------
/07-单例模式/07-07.singleton 块级作用域方式.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 单例模式
3 | * 作者: SHERlocked93
4 | * 功能: 块级作用域方式
5 | */
6 |
7 | let getInstance
8 |
9 | {
10 | let _instance = null // 存储单例
11 |
12 | const Singleton = function() {
13 | if (_instance) return _instance // 判断是否已有单例
14 | _instance = this
15 | this.init() // 初始化操作
16 | return _instance
17 | }
18 |
19 | Singleton.prototype.init = function() {
20 | this.foo = 'Singleton Pattern'
21 | }
22 |
23 | getInstance = function(bar) {
24 | if (_instance) return _instance
25 | _instance = new Singleton(bar)
26 | return _instance
27 | }
28 | }
29 |
30 | const visitor1 = getInstance()
31 | const visitor2 = getInstance()
32 |
33 | console.log(visitor1 === visitor2)
34 |
35 | // 输出: true
36 |
--------------------------------------------------------------------------------
/07-单例模式/07-08.singleton 模块模式方式.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 单例模式
3 | * 作者: SHERlocked93
4 | * 功能: 模块模式方式
5 | */
6 |
7 | const Singleton = (function() {
8 | let _instance = null // 存储单例
9 |
10 | const Singleton = function() {
11 | if (_instance) return _instance // 判断是否已有单例
12 | _instance = this
13 | this.init() // 初始化操作
14 | return _instance
15 | }
16 |
17 | Singleton.prototype.init = function() {
18 | this.foo = 'Singleton Pattern'
19 | }
20 |
21 | return {
22 | getInstance(bar) {
23 | if (_instance) return _instance
24 | _instance = new Singleton(bar)
25 | return _instance
26 | }
27 | }
28 | })()
29 |
30 | const visitor1 = Singleton.getInstance()
31 | const visitor2 = Singleton.getInstance()
32 |
33 | console.log(visitor1 === visitor2) // true
34 |
--------------------------------------------------------------------------------
/07-单例模式/07-09.singleton hungry 饿汉式.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 单例模式
3 | * 作者: SHERlocked93
4 | * 功能: 饿汉式
5 | */
6 |
7 | class FuncClass {
8 | constructor() { this.bar = 'bar' }
9 | }
10 |
11 | const HungrySingleton = (function() {
12 | const _instance = new FuncClass()
13 |
14 | return function() {
15 | return _instance
16 | }
17 | })()
18 |
19 | const visitor1 = new HungrySingleton()
20 | const visitor2 = new HungrySingleton()
21 |
22 | console.log(visitor1 === visitor2)
23 |
24 | // 输出: true
25 |
--------------------------------------------------------------------------------
/07-单例模式/07-10.singleton lazy 懒汉式.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 单例模式
3 | * 作者: SHERlocked93
4 | * 功能: 懒汉式
5 | */
6 |
7 | class FuncClass {
8 | constructor() { this.bar = 'bar' }
9 | }
10 |
11 | const LazySingleton = (function() {
12 | let _instance = null
13 |
14 | return function() {
15 | return _instance || (_instance = new FuncClass())
16 | }
17 | })()
18 |
19 | const visitor1 = new LazySingleton()
20 | const visitor2 = new LazySingleton()
21 |
22 | console.log(visitor1 === visitor2)
23 |
24 | // 输出: true
25 |
--------------------------------------------------------------------------------
/07-单例模式/07-11.singleton ES6.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 单例模式
3 | * 作者: SHERlocked93
4 | * 功能: ES6 方式
5 | */
6 |
7 | /* Person 类 */
8 | class Person {
9 | constructor(name, age) {
10 | this.name = name
11 | this.age = age
12 | }
13 | }
14 |
15 | /* 单例模式的赋能方法 */
16 | function Singleton(FuncClass) {
17 | let _instance
18 | return new Proxy(FuncClass, {
19 | construct(target, args) {
20 | return _instance || (_instance = Reflect.construct(FuncClass, args)) // 使用 new FuncClass(...args) 也可以
21 | }
22 | })
23 | }
24 |
25 | const PersonInstance = Singleton(Person)
26 |
27 | const person1 = new PersonInstance('张小帅', 25)
28 | const person2 = new PersonInstance('李小美', 23)
29 |
30 | console.log(person1 === person2) // true
31 |
--------------------------------------------------------------------------------
/07-单例模式/单例模式.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/07-单例模式/单例模式.png
--------------------------------------------------------------------------------
/07-单例模式/单例模式.xml:
--------------------------------------------------------------------------------
1 | 7VnbcuI4EP0aP0LZuhj7EXPJ1NRM7dZmameyLykFC/DEWKwsEsjXr2TLNsIiJOGSmdQWD9itltTuc7rVkhw4WKyvOFnOv7KYpg5w47UDhw4Anhd68k9JNlriIlhKZjyJS5nbCK6TJ6oVsZaukpjmhqJgLBXJUgv1BBOWZXQiDEXCOXs01aYsjQ3Bksyo0UkJrickpS2170ks5qUUB7CRf6LJbK5nRp5uuCOT+xlnq0xPl7GMli0LUo2iZ8znJGaPWyI4cuCAMybKp8V6QFPlVtNh4z2ttcWcZuIlHYKb6Wc3xZP+BoXL21vyCXynndo4salcQWPpGf3KuJizGctIOmqkUfG9VA3ryrdG5wtjSyn0pPAnFWKjYSYrwaRoLhapbs0FZ/e1o6UnotIKNfXer9OinK34RGv95Pf4n+midx26CxdNBn9dxbwDa99KulK2oIJvZD9OUyKSB3N8omkzq/Xqrn+yRM4MXM1xjDVTNcNh4JpDCMJnVOheDQzyYcuMRlSA8wqgECqneyDpSn+DMwqc/siJxs4odMKeet7FUtC1MF3PaZ48kbtCQaG3VAYXn4AjBw+lhKTJLJOCifQ85VLwQLlIZKj0dcMiieOCBym5o2lUR8CApUzqD4sYgNGUZUIzQEZ5BbEajK4dS0xro7ZDtAH/GfK2odbDu13X9U3UOlXcHskG2N0ZF4TmEGw6zemxRNhPb5MHwE8VyvmSZPJ5pp4t3JASydlAGu56VRdpgdFrlz9mpD/OE0Gvl6QIv0e5EpjUUoCPySJJlVP+pjwmGTF5ANxngt8S6y2y7MUayG80whOHFUSPTT73Qk2t+XYud/ejb4D32pANf+fUav0i/0yp1TewQz3wotTa55xsttR0Kts/Dwqs84zfpi8fSgtOmuf9E4Q3+BXD25L4WxR8cXgjDN45uAH4cNG9D4MTV064hy9aOdWLyTEhBT98SNUwXSKknhZfHp4e/rjJ13ff7sFth3+7GnYCC07HeLfttsP+9vzDdW2SppXIAXDkj8eDQT3djjKT1iVCTRcoi2OSzwvzvdOUPRibIIKgnReBH7RBhCA4E4phG8VRzwlCJwqdEVZhFfaVJPKcKKqi6o4bOPv/rtSuuACmkxfI9NW6BpfrpnFvCLY3PVZotnHUomrrk9KpeG7jYyOeSU0D6MP7pANJALaZdAry9FA3xAgHYYBgz0zSIAS2+hmBLgig3/zazAKoi4HXg6EHXQRRL8DHE82+I36nowvCRV+dODUIFrJxoswvhqVZXGlMUpLnyaQUapXzL+TheRZy37XWw6eu033PftSyr07f1b9InY7eqf77n32vLCMvzb7KrrOyD9hW2XJxlWUrcqKRE/zGtamPdjBA1tOcnqU69c+14UOWg7dfxeVNbYD3VJknhcO6+74oGMByGt5Kx00e3M6U7dz47JZBuohvftSpVb7cqJcurl6H6+3G4abJwls5+eXptcxib0ivW1hgCxSV7OjNvHkm1roGKZeHVhZup81q7ve6T8GWcA7U9j9EKq7DSMX14a3Fh7pPQc+mAbfrua653/ROQipv9zbFQ92dxf0t9ynytbldLdWb22s4+g8=
--------------------------------------------------------------------------------
/08-工厂模式/08-01.restaurant demo1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 工厂模式
3 | * 作者: SHERlocked93
4 | * 功能: 饭店例子
5 | */
6 |
7 | /* 饭店方法 */
8 | function restaurant(menu) {
9 | switch (menu) {
10 | case '鱼香肉丝':
11 | return new YuXiangRouSi()
12 | case '宫保鸡丁':
13 | return new GongBaoJiDing()
14 | default:
15 | throw new Error('这个菜本店没有 -。-')
16 | }
17 | }
18 |
19 | /* 鱼香肉丝类 */
20 | function YuXiangRouSi() {
21 | this.type = '鱼香肉丝'
22 | }
23 |
24 | YuXiangRouSi.prototype.eat = function() {
25 | console.log(this.type + ' 真香~')
26 | }
27 |
28 | /* 宫保鸡丁类 */
29 | function GongBaoJiDing() {
30 | this.type = '宫保鸡丁'
31 | }
32 |
33 | GongBaoJiDing.prototype.eat = function() {
34 | console.log(this.type + ' 让我想起了外婆做的菜~')
35 | }
36 |
37 | const dish1 = restaurant('鱼香肉丝')
38 | dish1.eat()
39 | const dish2 = restaurant('红烧排骨')
40 |
41 | // 输出: 鱼香肉丝 真香~
42 | // 输出: Error 这个菜本店没有 -。-
43 |
--------------------------------------------------------------------------------
/08-工厂模式/08-02.restaurant demo2 class.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 工厂模式
3 | * 作者: SHERlocked93
4 | * 功能: 饭店例子 class 方式改写
5 | */
6 |
7 | /* 饭店方法 */
8 | class Restaurant {
9 | static orderDish(menu) {
10 | switch (menu) {
11 | case '鱼香肉丝':
12 | return new YuXiangRouSi()
13 | case '宫保鸡丁':
14 | return new GongBaoJiDing()
15 | default:
16 | throw new Error('这个菜本店没有 -。-')
17 | }
18 | }
19 | }
20 |
21 | /* 鱼香肉丝类 */
22 | class YuXiangRouSi {
23 | constructor() {
24 | this.type = '鱼香肉丝'
25 | }
26 |
27 | eat() {
28 | console.log(this.type + ' 真香~')
29 | }
30 | }
31 |
32 | /* 宫保鸡丁类 */
33 | class GongBaoJiDing {
34 | constructor() {
35 | this.type = '宫保鸡丁'
36 | }
37 |
38 | eat() {
39 | console.log(this.type + ' 让我想起了外婆做的菜~')
40 | }
41 | }
42 |
43 | const dish1 = Restaurant.orderDish('鱼香肉丝')
44 | dish1.eat()
45 | const dish2 = Restaurant.orderDish('红烧排骨')
46 |
47 | // 输出: 鱼香肉丝 真香~
48 | // 输出: Error 这个菜本店没有 -。-
49 |
--------------------------------------------------------------------------------
/08-工厂模式/08-03.restaurant demo3 class.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 工厂模式
3 | * 作者: SHERlocked93
4 | * 功能: 饭店例子 灵活方式
5 | */
6 |
7 | /* 饭店方法 */
8 | class Restaurant {
9 | constructor() {
10 | this.menuData = {}
11 | }
12 |
13 | /**
14 | * 创建菜品
15 | * @param menu
16 | * @returns {Menu}
17 | */
18 | orderDish(menu) {
19 | if (!this.menuData[menu])
20 | throw new Error('这个菜本店没有 -。-')
21 | const { type, message } = this.menuData[menu]
22 | return new Menu(type, message)
23 | }
24 |
25 | /**
26 | * 增加菜品种类
27 | * @param menu
28 | * @param type
29 | * @param message
30 | */
31 | addMenu(menu, type, message) {
32 | if (this.menuData[menu]) {
33 | console.Info('已经有这个菜了!')
34 | return
35 | }
36 | this.menuData[menu] = { type, message }
37 | }
38 |
39 | /**
40 | * 移除菜品
41 | * @param menu
42 | */
43 | removeMenu(menu) {
44 | if (!this.menuData[menu]) return
45 | delete this.menuData[menu]
46 | }
47 | }
48 |
49 | /* 菜品类 */
50 | class Menu {
51 | constructor(type, message) {
52 | this.type = type
53 | this.message = message
54 | }
55 |
56 | eat() {
57 | console.log(this.type + this.message)
58 | }
59 | }
60 |
61 | const restaurant = new Restaurant()
62 | restaurant.addMenu('YuXiangRouSi', '鱼香肉丝', ' 真香~')
63 | restaurant.addMenu('GongBaoJiDing', '宫保鸡丁', ' 让我想起了外婆做的菜~')
64 |
65 | const dish1 = restaurant.orderDish('YuXiangRouSi')
66 | dish1.eat()
67 | const dish2 = restaurant.orderDish('HongShaoPaiGu')
68 |
69 | // 输出: 鱼香肉丝 真香~
70 | // 输出: Error 这个菜本店没有 -。-
71 |
--------------------------------------------------------------------------------
/08-工厂模式/08-04.factory demo1 class.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 工厂模式
3 | * 作者: SHERlocked93
4 | * 功能: 通用实现
5 | */
6 |
7 | /* 工厂类 */
8 | class Factory {
9 | static getInstance(type) {
10 | switch (type) {
11 | case 'Product1':
12 | return new Product1()
13 | case 'Product2':
14 | return new Product2()
15 | default:
16 | throw new Error('当前没有这个产品')
17 | }
18 | }
19 | }
20 |
21 | /* 产品类1 */
22 | class Product1 {
23 | constructor() {
24 | this.type = 'Product1'
25 | }
26 |
27 | operate() {
28 | console.log(this.type)
29 | }
30 | }
31 |
32 | /* 产品类2 */
33 | class Product2 {
34 | constructor() {
35 | this.type = 'Product2'
36 | }
37 |
38 | operate() {
39 | console.log(this.type)
40 | }
41 | }
42 |
43 | const prod1 = Factory.getInstance('Product1')
44 | prod1.operate()
45 | const prod2 = Factory.getInstance('Product3')
46 |
47 | // 输出: Product1
48 | // 输出: Error 当前没有这个产品
49 |
--------------------------------------------------------------------------------
/08-工厂模式/工厂模式-demo1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/08-工厂模式/工厂模式-demo1.png
--------------------------------------------------------------------------------
/08-工厂模式/工厂模式-概略图.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/08-工厂模式/工厂模式-概略图.png
--------------------------------------------------------------------------------
/08-工厂模式/工厂模式.xml:
--------------------------------------------------------------------------------
1 | 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
--------------------------------------------------------------------------------
/09-抽象工厂模式/09-01.restaurant demo1 prototype.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 抽象工厂模式
3 | * 作者: SHERlocked93
4 | * 功能: 饭店例子 使用原型方式
5 | */
6 |
7 | /* 饭店方法 */
8 | function Restaurant() {}
9 |
10 | Restaurant.orderDish = function(type) {
11 | switch (type) {
12 | case '鱼香肉丝':
13 | return new YuXiangRouSi()
14 | case '宫保鸡丁':
15 | return new GongBaoJiDing()
16 | case '紫菜蛋汤':
17 | return new ZiCaiDanTang()
18 | default:
19 | throw new Error('本店没有这个 -。-')
20 | }
21 | }
22 |
23 | /* 菜品抽象类 */
24 | function Dish() {
25 | this.kind = '菜'
26 | }
27 |
28 | /* 抽象方法 */
29 | Dish.prototype.eat = function() {
30 | throw new Error('抽象方法不能调用!')
31 | }
32 |
33 | /* 鱼香肉丝类 */
34 | function YuXiangRouSi() {
35 | this.type = '鱼香肉丝'
36 | }
37 |
38 | YuXiangRouSi.prototype = new Dish()
39 |
40 | YuXiangRouSi.prototype.eat = function() {
41 | console.log(this.kind + ' - ' + this.type + ' 真香~')
42 | }
43 |
44 | /* 宫保鸡丁类 */
45 | function GongBaoJiDing() {
46 | this.type = '宫保鸡丁'
47 | }
48 |
49 | GongBaoJiDing.prototype = new Dish()
50 |
51 | GongBaoJiDing.prototype.eat = function() {
52 | console.log(this.kind + ' - ' + this.type + ' 让我想起了外婆做的菜~')
53 | }
54 |
55 | const dish1 = Restaurant.orderDish('鱼香肉丝')
56 | dish1.eat()
57 | const dish2 = Restaurant.orderDish('红烧排骨')
58 |
59 | // 输出: 菜 - 鱼香肉丝 真香~
60 | // 输出: Error 本店没有这个 -。-
61 |
--------------------------------------------------------------------------------
/09-抽象工厂模式/09-02.restaurant demo2 class.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 抽象工厂模式
3 | * 作者: SHERlocked93
4 | * 功能: 饭店例子 引入抽象类
5 | */
6 |
7 | /* 饭店方法 */
8 | class Restaurant {
9 | static orderDish(type) {
10 | switch (type) {
11 | case '鱼香肉丝':
12 | return new YuXiangRouSi()
13 | case '宫保鸡丁':
14 | return new GongBaoJiDing()
15 | case '紫菜蛋汤':
16 | return new ZiCaiDanTang()
17 | default:
18 | throw new Error('本店没有这个 -。-')
19 | }
20 | }
21 | }
22 |
23 | /* 菜品抽象类 */
24 | class Dish {
25 | constructor() {
26 | if (new.target === Dish) {
27 | throw new Error('抽象类不能直接实例化!')
28 | }
29 | this.kind = '菜'
30 | }
31 |
32 | /* 抽象方法 */
33 | eat() {
34 | throw new Error('抽象方法不能调用!')
35 | }
36 | }
37 |
38 | /* 鱼香肉丝类 */
39 | class YuXiangRouSi extends Dish {
40 | constructor() {
41 | super()
42 | this.type = '鱼香肉丝'
43 | }
44 |
45 | eat() {
46 | console.log(this.kind + ' - ' + this.type + ' 真香~')
47 | }
48 | }
49 |
50 | /* 宫保鸡丁类 */
51 | class GongBaoJiDing extends Dish {
52 | constructor() {
53 | super()
54 | this.type = '宫保鸡丁'
55 | }
56 |
57 | eat() {
58 | console.log(this.kind + ' - ' + this.type + ' 让我想起了外婆做的菜~')
59 | }
60 | }
61 |
62 | /* 汤抽象类 */
63 | class Soup {
64 | constructor() {
65 | if (new.target === Dish) {
66 | throw new Error('抽象类不能直接实例化!')
67 | }
68 | this.kind = '汤'
69 | }
70 |
71 | /* 抽象方法 */
72 | drink() {
73 | throw new Error('抽象方法不能调用!')
74 | }
75 | }
76 |
77 |
78 | /* 紫菜蛋汤类 */
79 | class ZiCaiDanTang extends Soup {
80 | constructor() {
81 | super()
82 | this.type = '紫菜蛋汤'
83 | }
84 |
85 | drink() {
86 | console.log(this.kind + ' - ' + this.type + ' 我从小喝到大~')
87 | }
88 | }
89 |
90 | const soup1 = Restaurant.orderDish('紫菜蛋汤')
91 | soup1.drink()
92 | const dish1 = Restaurant.orderDish('鱼香肉丝')
93 | dish1.eat()
94 | const dish2 = Restaurant.orderDish('红烧排骨')
95 |
96 | // 输出: 汤 - 紫菜蛋汤 我从小喝到大~
97 | // 输出: 菜 - 鱼香肉丝 真香~
98 | // 输出: Error 本店没有这个 -。-
99 |
--------------------------------------------------------------------------------
/09-抽象工厂模式/09-03.restaurant demo3 class.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 抽象工厂模式
3 | * 作者: SHERlocked93
4 | * 功能: 饭店例子 引入抽象类
5 | */
6 |
7 | /**
8 | * 饭店 抽象类
9 | * 饭店都可以做菜和汤
10 | */
11 | class AbstractRestaurant {
12 | constructor() {
13 | if (new.target === AbstractDish) {
14 | throw new Error('抽象类不能直接实例化!')
15 | }
16 | this.signboard = '饭店'
17 | }
18 |
19 | /* 抽象方法:创建菜 */
20 | createDish() {
21 | throw new Error('抽象方法不能调用!')
22 | }
23 |
24 | /* 抽象方法:创建汤 */
25 | createSoup() {
26 | throw new Error('抽象方法不能调用!')
27 | }
28 | }
29 |
30 | /* 具体饭店类 */
31 | class Restaurant extends AbstractRestaurant {
32 | constructor() {
33 | super()
34 | }
35 |
36 | createDish(type) {
37 | switch (type) {
38 | case '鱼香肉丝':
39 | return new YuXiangRouSi()
40 | case '宫保鸡丁':
41 | return new GongBaoJiDing()
42 | default:
43 | throw new Error('本店没这个菜')
44 | }
45 | }
46 |
47 | createSoup(type) {
48 | switch (type) {
49 | case '紫菜蛋汤':
50 | return new ZiCaiDanTang()
51 | default:
52 | throw new Error('本店没这个汤')
53 | }
54 | }
55 | }
56 |
57 | /**
58 | * 菜 抽象类
59 | * 菜都有吃的功能
60 | */
61 | class AbstractDish {
62 | constructor() {
63 | if (new.target === AbstractDish) {
64 | throw new Error('抽象类不能直接实例化!')
65 | }
66 | this.kind = '菜'
67 | }
68 |
69 | /* 抽象方法 */
70 | eat() {
71 | throw new Error('抽象方法不能调用!')
72 | }
73 | }
74 |
75 | /* 菜 鱼香肉丝类 */
76 | class YuXiangRouSi extends AbstractDish {
77 | constructor() {
78 | super()
79 | this.type = '鱼香肉丝'
80 | }
81 |
82 | eat() {
83 | console.log(this.kind + ' - ' + this.type + ' 真香~')
84 | }
85 | }
86 |
87 | /* 菜 宫保鸡丁类 */
88 | class GongBaoJiDing extends AbstractDish {
89 | constructor() {
90 | super()
91 | this.type = '宫保鸡丁'
92 | }
93 |
94 | eat() {
95 | console.log(this.kind + ' - ' + this.type + ' 让我想起了外婆做的菜~')
96 | }
97 | }
98 |
99 | /**
100 | * 汤 抽象类
101 | * 汤都有喝的功能
102 | */
103 | class AbstractSoup {
104 | constructor() {
105 | if (new.target === AbstractDish) {
106 | throw new Error('抽象类不能直接实例化!')
107 | }
108 | this.kind = '汤'
109 | }
110 |
111 | /* 抽象方法 */
112 | drink() {
113 | throw new Error('抽象方法不能调用!')
114 | }
115 | }
116 |
117 | /* 汤 紫菜蛋汤类 */
118 | class ZiCaiDanTang extends AbstractSoup {
119 | constructor() {
120 | super()
121 | this.type = '紫菜蛋汤'
122 | }
123 |
124 | drink() {
125 | console.log(this.kind + ' - ' + this.type + ' 我从小喝到大~')
126 | }
127 | }
128 |
129 |
130 | const restaurant = new Restaurant()
131 |
132 | const soup1 = restaurant.createSoup('紫菜蛋汤')
133 | soup1.drink()
134 | const dish1 = restaurant.createDish('鱼香肉丝')
135 | dish1.eat()
136 | const dish2 = restaurant.createDish('红烧排骨')
137 |
138 | // 输出: 汤 - 紫菜蛋汤 我从小喝到大~
139 | // 输出: 菜 - 鱼香肉丝 真香~
140 | // 输出: Error 本店没有这个 -。-
141 |
--------------------------------------------------------------------------------
/09-抽象工厂模式/09-04.abstract factory demo1 class.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 抽象工厂模式
3 | * 作者: SHERlocked93
4 | * 功能: 通用实现 引入抽象产品类
5 | */
6 |
7 | /* 工厂方法 */
8 | class Factory {
9 | static getInstance(type) {
10 | switch (type) {
11 | case 'Product1':
12 | return new Product1()
13 | case 'Product2':
14 | return new Product2()
15 | default:
16 | throw new Error('当前没有这个产品')
17 | }
18 | }
19 | }
20 |
21 | /* 抽象类1 */
22 | class AbstractClass1 {
23 | constructor() {
24 | if (new.target === AbstractClass1) {
25 | throw new Error('抽象类不能直接实例化!')
26 | }
27 | this.kind = 'Abstract1'
28 | }
29 |
30 | /* 抽象方法 */
31 | operate() {
32 | throw new Error('抽象方法不能调用!')
33 | }
34 | }
35 |
36 | /* 产品类1 */
37 | class Product1 extends AbstractClass1 {
38 | constructor() {
39 | super()
40 | this.type = 'Product1'
41 | }
42 |
43 | operate() {
44 | console.log(this.kind + ' - ' + this.type + ' 第一个产品类~')
45 | }
46 | }
47 |
48 | /* 产品类2 */
49 | class Product2 extends AbstractClass1 {
50 | constructor() {
51 | super()
52 | this.type = 'Product2'
53 | }
54 |
55 | operate() {
56 | console.log(this.kind + ' - ' + this.type + ' 第二个产品类哦~')
57 | }
58 | }
59 |
60 | const prod1 = Factory.getInstance('Product1')
61 | prod1.operate()
62 | const prod3 = Factory.getInstance('Product3')
63 |
64 | // 输出: Abstract1 - Product1 第一个产品类~
65 | // 输出: Error 当前没有这个产品 -。-
66 |
--------------------------------------------------------------------------------
/09-抽象工厂模式/09-05.abstract factory demo2 class.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 抽象工厂模式
3 | * 作者: SHERlocked93
4 | * 功能: 通用实现 引入抽象工厂类
5 | */
6 |
7 | /**
8 | * 工厂 抽象类
9 | * 工厂的功能
10 | */
11 | class AbstractFactory {
12 | constructor() {
13 | if (new.target === AbstractProduct) {
14 | throw new Error('抽象类不能直接实例化!')
15 | }
16 | }
17 |
18 | /* 抽象方法 */
19 | createProduct1() {
20 | throw new Error('抽象方法不能调用!')
21 | }
22 | }
23 |
24 | /* 具体饭店类 */
25 | class Factory extends AbstractFactory {
26 | constructor() {
27 | super()
28 | }
29 |
30 | createProduct1(type) {
31 | switch (type) {
32 | case 'Product1':
33 | return new Product1()
34 | case 'Product2':
35 | return new Product2()
36 | default:
37 | throw new Error('当前没有这个产品 -。-')
38 | }
39 | }
40 | }
41 |
42 | /**
43 | * 抽象产品类
44 | */
45 | class AbstractProduct {
46 | constructor() {
47 | if (new.target === AbstractProduct) {
48 | throw new Error('抽象类不能直接实例化!')
49 | }
50 | this.kind = '抽象产品类1'
51 | }
52 |
53 | /* 抽象方法 */
54 | operate() {
55 | throw new Error('抽象方法不能调用!')
56 | }
57 | }
58 |
59 | /* 具体产品类1 */
60 | class Product1 extends AbstractProduct {
61 | constructor() {
62 | super()
63 | this.type = 'Product1'
64 | }
65 |
66 | operate() {
67 | console.log(this.kind + ' - ' + this.type)
68 | }
69 | }
70 |
71 | /* 具体产品类2 */
72 | class Product2 extends AbstractProduct {
73 | constructor() {
74 | super()
75 | this.type = 'Product2'
76 | }
77 |
78 | operate() {
79 | console.log(this.kind + ' - ' + this.type)
80 | }
81 | }
82 |
83 |
84 | const factory = new Factory()
85 |
86 | const prod1 = factory.createProduct1('Product1')
87 | prod1.operate()
88 | const prod2 = factory.createProduct1('Product3')
89 |
90 | // 输出: 抽象产品类1 - Product1
91 | // 输出: Error 当前没有这个产品 -。-
92 |
--------------------------------------------------------------------------------
/09-抽象工厂模式/抽象工厂模式.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/09-抽象工厂模式/抽象工厂模式.png
--------------------------------------------------------------------------------
/09-抽象工厂模式/抽象工厂模式.xml:
--------------------------------------------------------------------------------
1 | 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
--------------------------------------------------------------------------------
/10-建造者模式/10-01.car demo1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 建造者模式
3 | * 作者: SHERlocked93
4 | * 功能: car 组装汽车例子
5 | */
6 |
7 | // 建造者,汽车部件厂家
8 | function CarBuilder({ color = 'white', weight = 0 }) {
9 | this.color = color
10 | this.weight = weight
11 | }
12 |
13 | // 生产部件,轮胎
14 | CarBuilder.prototype.buildTyre = function(type) {
15 | switch (type) {
16 | case 'small':
17 | this.tyreType = '小号轮胎'
18 | this.tyreIntro = '正在使用小号轮胎'
19 | break
20 | case 'normal':
21 | this.tyreType = '中号轮胎'
22 | this.tyreIntro = '正在使用中号轮胎'
23 | break
24 | case 'big':
25 | this.tyreType = '大号轮胎'
26 | this.tyreIntro = '正在使用大号轮胎'
27 | break
28 | }
29 | }
30 |
31 | // 生产部件,发动机
32 | CarBuilder.prototype.buildEngine = function(type) {
33 | switch (type) {
34 | case 'small':
35 | this.engineType = '小马力发动机'
36 | this.engineIntro = '正在使用小马力发动机'
37 | break
38 | case 'normal':
39 | this.engineType = '中马力发动机'
40 | this.engineIntro = '正在使用中马力发动机'
41 | break
42 | case 'big':
43 | this.engineType = '大马力发动机'
44 | this.engineIntro = '正在使用大马力发动机'
45 | break
46 | }
47 | }
48 |
49 | /**
50 | * 奔驰厂家,负责最终汽车产品的装配
51 | */
52 | function benChiDirector(tyre, engine, param) {
53 | var _car = new CarBuilder(param)
54 | _car.buildTyre(tyre)
55 | _car.buildEngine(engine)
56 | return _car
57 | }
58 |
59 | // 获得产品实例
60 | var benchi1 = benChiDirector('small', 'big', { color: 'red', weight: '1600kg' })
61 |
62 | console.log(benchi1)
63 |
64 | // 输出:
65 | // {
66 | // color: "red"
67 | // weight: "1600kg"
68 | // tyre: Tyre {tyreType: "小号轮胎", tyreIntro: "正在使用小号轮胎"}
69 | // engine: Engine {engineType: "大马力发动机", engineIntro: "正在使用大马力发动机"}
70 | // }
71 |
--------------------------------------------------------------------------------
/10-建造者模式/10-02.car demo2 class.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 建造者模式
3 | * 作者: SHERlocked93
4 | * 功能: car 组装汽车例子 ES6 class方式
5 | */
6 |
7 | // 建造者,汽车部件厂家
8 | class CarBuilder {
9 | constructor({ color = 'white', weight = 0 }) {
10 | this.color = color
11 | this.weight = weight
12 | }
13 |
14 | /**
15 | * 生产轮胎
16 | * @param type
17 | */
18 | buildTyre(type) {
19 | const tyre = {}
20 | switch (type) {
21 | case 'small':
22 | tyre.tyreType = '小号轮胎'
23 | tyre.tyreIntro = '正在使用小号轮胎'
24 | break
25 | case 'normal':
26 | tyre.tyreType = '中号轮胎'
27 | tyre.tyreIntro = '正在使用中号轮胎'
28 | break
29 | case 'big':
30 | tyre.tyreType = '大号轮胎'
31 | tyre.tyreIntro = '正在使用大号轮胎'
32 | break
33 | }
34 | this.tyre = tyre
35 | }
36 |
37 | /**
38 | * 生产发动机
39 | * @param type
40 | */
41 | buildEngine(type) {
42 | const engine = {}
43 | switch (type) {
44 | case 'small':
45 | engine.engineType = '小马力发动机'
46 | engine.engineIntro = '正在使用小马力发动机'
47 | break
48 | case 'normal':
49 | engine.engineType = '中马力发动机'
50 | engine.engineIntro = '正在使用中马力发动机'
51 | break
52 | case 'big':
53 | engine.engineType = '大马力发动机'
54 | engine.engineIntro = '正在使用大马力发动机'
55 | break
56 | }
57 | this.engine = engine
58 | }
59 | }
60 |
61 | /**
62 | * 指挥者,负责最终汽车产品的装配
63 | */
64 | class BenChiDirector {
65 | constructor(tyre, engine, param) {
66 | const _car = new CarBuilder(param)
67 | _car.buildTyre(tyre)
68 | _car.buildEngine(engine)
69 | return _car
70 | }
71 | }
72 |
73 | // 获得产品实例
74 | const benchi1 = new BenChiDirector('small', 'big', { color: 'red', weight: '1600kg' })
75 |
76 | console.log(benchi1)
77 |
78 | // 输出:
79 | // {
80 | // color: "red"
81 | // weight: "1600kg"
82 | // tyre: Tyre {tyreType: "小号轮胎", tyreIntro: "正在使用小号轮胎"}
83 | // engine: Engine {engineType: "大马力发动机", engineIntro: "正在使用大马力发动机"}
84 | // }
85 |
--------------------------------------------------------------------------------
/10-建造者模式/10-03.car demo3 chain.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 建造者模式
3 | * 作者: SHERlocked93
4 | * 功能: car 组装汽车例子 chain 方式
5 | */
6 |
7 | // 建造者,汽车部件厂家
8 | class CarBuilder {
9 | constructor({ color = 'white', weight = '0' }) {
10 | this.color = color
11 | this.weight = weight
12 | }
13 |
14 | /**
15 | * 生产部件,轮胎
16 | * @param type
17 | * @returns {CarBuilder}
18 | */
19 | buildTyre(type) {
20 | const tyre = {}
21 | switch (type) {
22 | case 'small':
23 | tyre.tyreType = '小号轮胎'
24 | tyre.tyreIntro = '正在使用小号轮胎'
25 | break
26 | case 'normal':
27 | tyre.tyreType = '中号轮胎'
28 | tyre.tyreIntro = '正在使用中号轮胎'
29 | break
30 | case 'big':
31 | tyre.tyreType = '大号轮胎'
32 | tyre.tyreIntro = '正在使用大号轮胎'
33 | break
34 | }
35 | this.tyre = tyre
36 | return this
37 | }
38 |
39 | /**
40 | * 生产部件,发动机
41 | * @param type
42 | * @returns {CarBuilder}
43 | */
44 | buildEngine(type) {
45 | const engine = {}
46 | switch (type) {
47 | case 'small':
48 | engine.engineType = '小马力发动机'
49 | engine.engineIntro = '正在使用小马力发动机'
50 | break
51 | case 'normal':
52 | engine.engineType = '中马力发动机'
53 | engine.engineIntro = '正在使用中马力发动机'
54 | break
55 | case 'big':
56 | engine.engineType = '大马力发动机'
57 | engine.engineIntro = '正在使用大马力发动机'
58 | break
59 | }
60 | this.engine = engine
61 | return this
62 | }
63 | }
64 |
65 | // 汽车装配,获得产品实例
66 | const benchi1 = new CarBuilder({ color: 'red', weight: '1600kg' })
67 | .buildTyre('small')
68 | .buildEngine('big')
69 |
70 |
71 | console.log(benchi1)
72 |
73 | // 输出:
74 | // {
75 | // color: "red"
76 | // weight: "1600kg"
77 | // tyre: Tyre {tyre: "小号轮胎", tyreIntro: "正在使用小号轮胎"}
78 | // engine: Engine {engine: "大马力发动机", engineIntro: "正在使用大马力发动机"}
79 | // }
80 |
--------------------------------------------------------------------------------
/10-建造者模式/10-04.builder demo1 class.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 建造者模式
3 | * 作者: SHERlocked93
4 | * 功能: 通用实现 ES6 class方式
5 | */
6 |
7 | // 建造者,部件生产
8 | class ProductBuilder {
9 | constructor(param) {
10 | this.param = param
11 | }
12 |
13 | /**
14 | * 生产部件,part1
15 | */
16 | buildPart1() {
17 | // ... Part1 生产过程
18 | this.part1 = 'part1'
19 |
20 | }
21 |
22 | /**
23 | * 生产部件,part2
24 | */
25 | buildPart2() {
26 | // ... Part2 生产过程
27 | this.part2 = 'part2'
28 | }
29 | }
30 |
31 | /**
32 | * 指挥者,负责最终产品的装配
33 | */
34 | class Director {
35 | constructor(param) {
36 | const _prod = new ProductBuilder(param)
37 | _prod.buildPart1()
38 | _prod.buildPart2()
39 | return _prod
40 | }
41 | }
42 |
43 | // 获得产品实例
44 | const prod = new Director('param')
45 |
46 | console.log(prod)
47 |
--------------------------------------------------------------------------------
/10-建造者模式/10-05.builder demo2 chain.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 建造者模式
3 | * 作者: SHERlocked93
4 | * 功能: 通用实现 chain 方式
5 | */
6 |
7 | // 建造者,汽车部件厂家
8 | class CarBuilder {
9 | constructor(param) {
10 | this.param = param
11 | }
12 |
13 | /**
14 | * 生产部件,part1
15 | * @returns {CarBuilder}
16 | */
17 | buildPart1() {
18 | this.part1 = 'part1'
19 | return this
20 | }
21 |
22 | /**
23 | * 生产部件,part2
24 | * @returns {CarBuilder}
25 | */
26 | buildPart2() {
27 | this.part2 = 'part2'
28 | return this
29 | }
30 | }
31 |
32 | // 汽车装配,获得产品实例
33 | const benchi1 = new CarBuilder('param')
34 | .buildPart1()
35 | .buildPart2()
36 |
37 |
--------------------------------------------------------------------------------
/10-建造者模式/10-06.builder demo1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 建造者模式
3 | * 作者: SHERlocked93
4 | * 功能: 实战使用建造者模式 重构多参数的构造函数
5 | */
6 |
7 | // 汽车建造者
8 | class CarBuilder {
9 | constructor(engine, weight, height, color, tyre, name, type) {
10 | this.engine = engine
11 | this.weight = weight
12 | this.height = height
13 | this.color = color
14 | this.tyre = tyre
15 | this.name = name
16 | this.type = type
17 | }
18 |
19 | setCarProperty(key, value) {
20 | if (Object.getOwnPropertyNames(this).includes(key)) {
21 | this[key] = value
22 | return this
23 | }
24 | throw new Error(`Key error : ${ key } 不是本实例上的属性`)
25 | }
26 | }
27 |
28 | // const benchi = new CarBuilder('大马力发动机', '2ton', '2000mm', 'white', '大号轮胎', '奔驰', 'AMG') // 原本使用方式
29 |
30 | const benchi = new CarBuilder()
31 | .setCarProperty('engine', '大马力发动机')
32 | .setCarProperty('weight', '2ton')
33 | .setCarProperty('height', '2000mm')
34 | .setCarProperty('color', 'white')
35 | .setCarProperty('tyre', '大号轮胎')
36 | .setCarProperty('name', '奔驰')
37 | .setCarProperty('type', 'AMG')
38 |
--------------------------------------------------------------------------------
/10-建造者模式/10-07.builder demo2.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 建造者模式
3 | * 作者: SHERlocked93
4 | * 功能: 实战使用建造者模式 重构多参数的构造函数
5 | */
6 |
7 | // 汽车建造者
8 | class CarBuilder {
9 | constructor(engine, weight, height, color, tyre, name, type) {
10 | this.engine = engine
11 | this.weight = weight
12 | this.height = height
13 | this.color = color
14 | this.tyre = tyre
15 | this.name = name
16 | this.type = type
17 | }
18 |
19 | setPropertyFuncChain() {
20 | Object.getOwnPropertyNames(this)
21 | .forEach(key => {
22 | const funcName = 'set' + key.replace(/^\w/g, str => str.toUpperCase())
23 | this[funcName] = value => {
24 | this[key] = value
25 | return this
26 | }
27 | })
28 | return this
29 | }
30 | }
31 |
32 | const benchi = new CarBuilder().setPropertyFuncChain()
33 | .setEngine('大马力发动机')
34 | .setWeight('2ton')
35 | .setHeight('2000mm')
36 | .setColor('white')
37 | .setTyre('大号轮胎')
38 | .setName('奔驰')
39 | .setType('AMG')
40 |
--------------------------------------------------------------------------------
/10-建造者模式/10-08.builder react.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 建造者模式
3 | * 作者: SHERlocked93
4 | * 功能: 重构react组件形式
5 | */
6 |
7 | export const ComponentBuilder = (displayName = 'Component') => {
8 | let _render, _componentDidMount, _propTypes, _mapStateToProps, _mapDispatchToProps
9 |
10 | const builder = {
11 | render: renderFn => {
12 | _render = renderFn
13 | return builder
14 | },
15 | propTypes: types => {
16 | _propTypes = types
17 | return builder
18 | },
19 | componentDidMount: didMountFn => {
20 | _componentDidMount = didMountFn
21 | return builder
22 | },
23 | mapStateToProps: statePropsFn => {
24 | _mapStateToProps = statePropsFn
25 | return builder
26 | },
27 | mapDispatchToProps: dispatchPropsFn => {
28 | _mapDispatchToProps = dispatchPropsFn
29 | return builder
30 | },
31 | build: () => {
32 | if (!_render) {
33 | throw new Error('Component render method required')
34 | }
35 |
36 | // noinspection JSRedeclarationOfBlockScope
37 | let Comp
38 | if (!_componentDidMount) {
39 | // Without lifecycle methods, component can just be a pure function
40 | Comp = _render
41 | } else {
42 | Comp = class extends Component {
43 | render() {
44 | return _render(this.props)
45 | }
46 |
47 | componentDidMount() {
48 | if (_componentDidMount) _componentDidMount(this.props)
49 | }
50 | }
51 | }
52 |
53 | Comp.propTypes = _propTypes || {}
54 | Comp.displayName = displayName
55 |
56 | if (_mapStateToProps || _mapDispatchToProps) {
57 | // If redux methods are provided, connect to store
58 | return connect(_mapStateToProps, _mapDispatchToProps)(Comp)
59 | }
60 |
61 | return Comp
62 | }
63 | }
64 |
65 | return builder
66 | }
67 |
--------------------------------------------------------------------------------
/10-建造者模式/建造者模式.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/10-建造者模式/建造者模式.png
--------------------------------------------------------------------------------
/10-建造者模式/建造者模式.xml:
--------------------------------------------------------------------------------
1 |
2 | 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
--------------------------------------------------------------------------------
/11-代理模式/11-01.superstar demo1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 代理模式
3 | * 作者: SHERlocked93
4 | * 功能: 明星例子
5 | */
6 |
7 | /* 明星 */
8 | var SuperStar = {
9 | name: '小鲜肉',
10 | playAdvertisement: function(ad) {
11 | console.log(ad)
12 | }
13 | }
14 |
15 | /* 经纪人 */
16 | var ProxyAssistant = {
17 | name: '经纪人张某',
18 | playAdvertisement: function(reward, ad) {
19 | if (reward > 1000000) { // 如果报酬超过100w
20 | console.log('没问题,我们小鲜鲜最喜欢拍广告了!')
21 | SuperStar.playAdvertisement(ad)
22 | } else
23 | console.log('没空,滚!')
24 | }
25 | }
26 |
27 | ProxyAssistant.playAdvertisement(10000, '纯蒸酸牛奶,味道纯纯,尽享纯蒸')
28 | // 输出: 没空,滚
29 |
--------------------------------------------------------------------------------
/11-代理模式/11-02.superstar demo2.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 代理模式
3 | * 作者: SHERlocked93
4 | * 功能: 明星例子 demo2
5 | */
6 |
7 | /* 明星 */
8 | const SuperStar = {
9 | name: '小鲜肉',
10 | playAdvertisement(ad) {
11 | console.log(ad)
12 | }
13 | }
14 |
15 | /* 经纪人 */
16 | const ProxyAssistant = {
17 | name: '经纪人张某',
18 | scheduleTime() {
19 | return new Promise((resolve, reject) => {
20 | setTimeout(() => {
21 | console.log('小鲜鲜有空了')
22 | resolve()
23 | }, 2000) // 发现明星有空了
24 | })
25 | },
26 | playAdvertisement(reward, ad) {
27 | if (reward > 1000000) { // 如果报酬超过100w
28 | console.log('没问题,我们小鲜鲜最喜欢拍广告了!')
29 | ProxyAssistant.scheduleTime() // 安排上了
30 | .then(() => SuperStar.playAdvertisement(ad))
31 | } else
32 | console.log('没空,滚!')
33 | }
34 | }
35 |
36 | ProxyAssistant.playAdvertisement(10000, '纯蒸酸牛奶,味道纯纯,尽享纯蒸')
37 | // 输出: 没空,滚
38 |
39 | ProxyAssistant.playAdvertisement(1000001, '纯蒸酸牛奶,味道纯纯,尽享纯蒸')
40 | // 输出: 没问题,我们小鲜鲜最喜欢拍广告了!
41 | // 2秒后
42 | // 输出: 小鲜鲜有空了
43 | // 输出: 纯蒸酸牛奶,味道纯纯,尽享纯蒸
44 |
--------------------------------------------------------------------------------
/11-代理模式/11-03.superstar demo3 Proxy.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 代理模式
3 | * 作者: SHERlocked93
4 | * 功能: 明星例子 demo3 使用 Proxy
5 | */
6 |
7 | /* 明星 */
8 | const SuperStar = {
9 | name: '小鲜肉',
10 | scheduleFlag: false, // 档期标识位,false-没空(默认值),true-有空
11 | playAdvertisement(ad) {
12 | console.log(ad)
13 | }
14 | }
15 |
16 | /* 经纪人 */
17 | const ProxyAssistant = {
18 | name: '经纪人张某',
19 | scheduleTime(ad) {
20 | const schedule = new Proxy(SuperStar, { // 在这里监听 scheduleFlag 值的变化
21 | set(obj, prop, val) {
22 | if (prop !== 'scheduleFlag') return
23 | if (obj.scheduleFlag === false &&
24 | val === true) { // 小鲜肉现在有空了
25 | obj.scheduleFlag = true
26 | obj.playAdvertisement(ad) // 安排上了
27 | }
28 | }
29 | })
30 |
31 | setTimeout(() => {
32 | console.log('小鲜鲜有空了')
33 | schedule.scheduleFlag = true // 发现明星有空了
34 | }, 2000)
35 | },
36 | playAdvertisement(reward, ad) {
37 | if (reward > 1000000) { // 如果报酬超过100w
38 | console.log('没问题,我们小鲜鲜最喜欢拍广告了!')
39 | ProxyAssistant.scheduleTime(ad)
40 | } else
41 | console.log('没空,滚!')
42 | }
43 | }
44 |
45 | ProxyAssistant.playAdvertisement(10000, '纯蒸酸牛奶,味道纯纯,尽享纯蒸')
46 | // 输出: 没空,滚
47 |
48 | ProxyAssistant.playAdvertisement(1000001, '纯蒸酸牛奶,味道纯纯,尽享纯蒸')
49 | // 输出: 没问题,我们小鲜鲜最喜欢拍广告了!
50 | // 2秒后
51 | // 输出: 小鲜鲜有空了
52 | // 输出: 纯蒸酸牛奶,味道纯纯,尽享纯蒸
53 |
--------------------------------------------------------------------------------
/11-代理模式/11-04.superstar demo4 Object.defineProperty.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 代理模式
3 | * 作者: SHERlocked93
4 | * 功能: 明星例子 demo4 使用 Obeject.defineProperty
5 | */
6 |
7 | /* 明星 */
8 | const SuperStar = {
9 | name: '小鲜肉',
10 | scheduleFlagActually: false, // 档期标识位,false-没空(默认值),true-有空
11 | playAdvertisement(ad) {
12 | console.log(ad)
13 | }
14 | }
15 |
16 | /* 经纪人 */
17 | const ProxyAssistant = {
18 | name: '经纪人张某',
19 | scheduleTime(ad) {
20 | Object.defineProperty(SuperStar, 'scheduleFlag', { // 在这里监听 scheduleFlag 值的变化
21 | get() {
22 | return SuperStar.scheduleFlagActually
23 | },
24 | set(val) {
25 | if (SuperStar.scheduleFlagActually === false &&
26 | val === true) { // 小鲜肉现在有空了
27 | SuperStar.scheduleFlagActually = true
28 | SuperStar.playAdvertisement(ad) // 安排上了
29 | }
30 | }
31 | })
32 |
33 | setTimeout(() => {
34 | console.log('小鲜鲜有空了')
35 | SuperStar.scheduleFlag = true
36 | }, 2000) // 明星有空了
37 | },
38 | playAdvertisement(reward, ad) {
39 | if (reward > 1000000) { // 如果报酬超过100w
40 | console.log('没问题,我们小鲜鲜最喜欢拍广告了!')
41 | ProxyAssistant.scheduleTime(ad)
42 | } else
43 | console.log('没空,滚!')
44 | }
45 | }
46 |
47 | ProxyAssistant.playAdvertisement(10000, '纯蒸酸牛奶,味道纯纯,尽享纯蒸')
48 | // 输出: 没空,滚
49 |
50 | ProxyAssistant.playAdvertisement(1000001, '纯蒸酸牛奶,味道纯纯,尽享纯蒸')
51 | // 输出: 没问题,我们小鲜鲜最喜欢拍广告了!
52 | // 2秒后
53 | // 输出: 小鲜鲜有空了
54 | // 输出: 纯蒸酸牛奶,味道纯纯,尽享纯蒸
55 |
--------------------------------------------------------------------------------
/11-代理模式/代理模式.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/11-代理模式/代理模式.png
--------------------------------------------------------------------------------
/11-代理模式/代理模式.xml:
--------------------------------------------------------------------------------
1 | 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
--------------------------------------------------------------------------------
/11-代理模式/正向代理与反向代理.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/11-代理模式/正向代理与反向代理.png
--------------------------------------------------------------------------------
/12-享元模式/12-01.superstar demo1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 享元模式
3 | * 作者: SHERlocked93
4 | * 功能: 考驾照例子
5 | */
6 |
7 |
8 | var candidateNum = 10 // 考生数量
9 | var examCarNum = 0 // 驾考车的数量
10 |
11 | /**
12 | * 驾考车构造函数
13 | * @constructor
14 | */
15 | function ExamCar(carType) {
16 | examCarNum++
17 | this.carId = examCarNum
18 | this.carType = carType ? '手动档' : '自动档'
19 | }
20 |
21 | ExamCar.prototype.examine = function(candidateId) {
22 | console.log('考生- ' + candidateId + ' 在' + this.carType + '驾考车- ' + this.carId + ' 上考试')
23 | }
24 |
25 | for (var candidateId = 1; candidateId <= candidateNum; candidateId++) {
26 | var examCar = new ExamCar(candidateId % 2)
27 | examCar.examine(candidateId)
28 | }
29 |
30 | console.log('驾考车总数- ' + examCarNum)
31 | // 输出: 驾考车总数 - 10
32 |
--------------------------------------------------------------------------------
/12-享元模式/12-02.superstar demo2.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 享元模式
3 | * 作者: SHERlocked93
4 | * 功能: 考驾照例子
5 | */
6 |
7 |
8 | var candidateNum = 10 // 考生数量
9 | var examCarNum = 0 // 驾考车的数量
10 |
11 | /**
12 | * 驾考车构造函数
13 | * @constructor
14 | */
15 | function ExamCar(carType) {
16 | examCarNum++
17 | this.carId = examCarNum
18 | this.carType = carType ? '手动档' : '自动档'
19 | }
20 |
21 | ExamCar.prototype.examine = function(candidateId) {
22 | console.log('考生- ' + candidateId + ' 在' + this.carType + '驾考车- ' + this.carId + ' 上考试')
23 | }
24 |
25 | var manualExamCar = new ExamCar(true)
26 | var autoExamCar = new ExamCar(false)
27 |
28 | for (var candidateId = 1; candidateId <= candidateNum; candidateId++) {
29 | var examCar = candidateId % 2 ? manualExamCar : autoExamCar
30 | examCar.examine(candidateId)
31 | }
32 |
33 | console.log('驾考车总数- ' + examCarNum)
34 | // 输出: 驾考车总数 - 2
35 |
--------------------------------------------------------------------------------
/12-享元模式/12-03.superstar demo3.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 享元模式
3 | * 作者: SHERlocked93
4 | * 功能: 考驾照例子
5 | */
6 |
7 | let examCarNum = 0 // 驾考车总数
8 |
9 | /* 驾考车对象 */
10 | class ExamCar {
11 | constructor(carType) {
12 | examCarNum++
13 | this.carId = examCarNum
14 | this.carType = carType ? '手动档' : '自动档'
15 | this.usingState = false // 是否正在使用
16 | }
17 |
18 | /**
19 | * 在本车上考试
20 | * @param candidateId
21 | */
22 | examine(candidateId) {
23 | return new Promise((resolve => {
24 | this.usingState = true
25 | console.log(`考生- ${ candidateId } 开始在${ this.carType }驾考车- ${ this.carId } 上考试`)
26 | setTimeout(() => {
27 | this.usingState = false
28 | console.log(`%c考生- ${ candidateId } 在${ this.carType }驾考车- ${ this.carId } 上考试完毕`, 'color:#f40')
29 | resolve() // 0~2秒后考试完毕
30 | }, Math.random() * 2000)
31 | }))
32 | }
33 | }
34 |
35 | /* 手动档汽车对象池 */
36 | ManualExamCarPool = {
37 | _pool: [], // 驾考车对象池
38 | _candidateQueue: [], // 考生队列
39 |
40 | /**
41 | * 注册考生 ID 列表
42 | * @param candidateList
43 | */
44 | registCandidates(candidateList) {
45 | candidateList.forEach(candidateId => this.registCandidate(candidateId))
46 | },
47 |
48 | /**
49 | * 注册手动档考生
50 | */
51 | registCandidate(candidateId) {
52 | const examCar = this.getManualExamCar() // 找一个未被占用的手动档驾考车
53 | if (examCar) {
54 | examCar.examine(candidateId) // 开始考试,考完了让队列中的下一个考生开始考试
55 | .then(() => {
56 | const nextCandidateId = this._candidateQueue.length && this._candidateQueue.shift()
57 | nextCandidateId && this.registCandidate(nextCandidateId)
58 | })
59 | } else this._candidateQueue.push(candidateId)
60 | },
61 |
62 | /**
63 | * 注册手动档车
64 | */
65 | initManualExamCar(manualExamCarNum) {
66 | for (let i = 1; i <= manualExamCarNum; i++) {
67 | this._pool.push(new ExamCar(true))
68 | }
69 | },
70 |
71 | /**
72 | * 获取状态为未被占用的手动档车
73 | * @returns {*}
74 | */
75 | getManualExamCar() {
76 | return this._pool.find(car => !car.usingState)
77 | }
78 | }
79 |
80 | ManualExamCarPool.initManualExamCar(3) // 一共有3个驾考车
81 | ManualExamCarPool.registCandidates([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) // 10个考生来考试
82 |
--------------------------------------------------------------------------------
/12-享元模式/Nodejs 线程池.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/12-享元模式/Nodejs 线程池.png
--------------------------------------------------------------------------------
/12-享元模式/享元模式.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/12-享元模式/享元模式.png
--------------------------------------------------------------------------------
/12-享元模式/享元模式.xml:
--------------------------------------------------------------------------------
1 | 7VtRl6I2GP01Ps4eICD4ODpj27NtT1vP2U6f9qQSgd1ILMZR99c3SCKGgOIIQzjOzsOaLyGQey/3CznJAEyWu58SuAp/Iz7CA8vwdwPwNLAs0wAG+y+N7EXEtrJIkER+FjPywCz6gURDHt1EPlrzWBaihGAareTgnMQxmlMpBpOEbOVmC4J9KbCCAZIeIw3M5hAjpdnfkU/DLOpZbh7/GUVByO/seCCrWELRlve7DqFPtich8DwAk4QQmv1a7iYIp+DJsEwrao/PlaCY1rlg/7L4+uXz2PzLnGwW0x9/ev/hrw+8l1eIN3y8/GHpXgCQkE3so7QTcwDG2zCiaLaC87R2yzhnsZAuMa/24To8tl2QmE7hMsIp919Q4sMYsjC/JUoo2lWOxTwixKSFyBLRZM+a8AtsG3xysouErjz+5NucJHPEoQ9PCAKmzcXBhREce8/BYz84fuVYfrNfrOUv0/HqdRE44PUz/f7w+4NZA8yAobm6BI2CQylaXPDwX4yKoiqDzDUkvByvHlwuaAuthpW3iDCeEEySw7XgcZz+sfiaJuQ7EjUxidE18J8nukiKCn5n8Frtwjs9/LvqhW8SVl7ruJKmLUfVtIidgm6bLYEOVFE/KrCzsVEZ23KJngDOQxBHQcyKc4YjYvFxilTEUtUjr1hGvp/eppTMnG6jjDeeeS3QBY+yNSks2iVvjkirzRtTjVdHGxs3h6BrHwc9NnKrghaNjByochzfoafUZ0pHTwHe5ZeEdcO+aaqQrpxjV+TlzuEfFSbopcm5hIPWkrPp9MjXrWHn8/Nhj33dqaBFJ1+3FXwnd+jr9ZnS0tdHPff16+HXz9dr5FZtfB24dte+XkOy2vq6V0GLRr4utN+rlZf6uOq68qJO7p7uMJtez6NO2dTq0wK67bodO7lAp49OXkmLTk7e8spWG05+Ba66Orn63fl8f07+Bh5ld/rUtZe7PfJyx+t6Vm7V+IjR1svdClo08nKgynF6h65Snykd54d2jU8rnVdb3gC/dqstoOXP26NRSfzc5lpX51LbM2XUxaSks1mRXePTqBHpH/EvSv/dKSju8LKNsknN+6pf7F08S0PsP6b7DtN0gOF6Hc0Lgi8Ai3YRfeF16e9/0jzARpqVnnY8LRwKe17IyBD7Ea20OmbjexFt08JJP2kx7+hQEj1dy+CabJI5OmdyWTsKkwCdM0NhJMgX+y8vzxmcEq5FLEEY0ugVSU9bJgB+hz9IxIaW682QX3nHHsldZAPnV+UyUjtyC47tFfYbZsgoHR30eBz2DRIFZ/w4ZZwkNCQBiSH+lZAVF943ROmeqxJuKJEl+1ZxqTJtQvzNS9ZoWrO1xXibG9mq+bAnm/Ei9+gP9i+wD3rKfo39DJdyUTsUaZOL7Lovtpgw6JKMgJyMhsZbk1FhIus4hY7aTkbDD4e6XcZi91hzMn4nh3I/2G+A/ZH27JceLVI/laZ4v83M0jJmFFKkyKPvK3C3HWoCZvFQE1DXpS1xfkk61HT9mSZWzM+eZX6fn+ADz/8D7ZnbcpswEIafxpfJAILYvowPbafTtGndpoebjAxrUCIQFXKM8/RdgbDBuI6dpokv4pnY7I8kpP1Wi6R0yDDO30qaRhciAN5xrCDvkFHHcWyLWPijlaVRXNcplVCyoNSstTBh91BVNeqcBZAZrZSUEFyxtCn6IknAVw2NSikWzWIzwYOGkNIQGt3QwsSnHFrFvrNARaXac7pr/R2wMDJP9nqkvBHTqqxpN4toIBY1iYw7ZCiFUOVVnA+Ba+et3MLt8/FUnHxz+zmb3Cw/fxnTk7KxN4dUWY1AQqIe3fSvi2tm//riv//04+fnb1d5PLiRJ7Zhmall5S8I0H3GBD4Vi/FaGEgxTwLQLdpoCakiEYqE8g9CpEa8AaWWJgzoXAmUIhVzcxdHIJc/0LAq46c2Tr3KHOX1m6OlsTIlxS0MBRey6Caxis/qToUWqQxmIlFvaMy4rnwFMqAJRbkcqR7eRmA84FZTLhNz6cOOcsaVisoQdrXXXcUOTjoQMeA4sZ4EThW7a3aOmuAPV+XWhPHCQD4glkwn7yifmye1AoDFxYyqU+N0CnxA/duwCIAahlnxwSKm1ojFIXaMsyl++5yl11QqfSnidK5AZng9oopOaQbXttPL8e80TUJsIaBZtAqtnQzvQCrIH0Gx7XXTimcZP5gsd0K6GJKFsqglDZMJolq+sO3+f0JFjgDVR1BTIW6PiFS33wRl9/bCVGlPTsl7pfQwJds5e1lKZ6+U9plLZ87LYuoeAaYJSPT09VexwO/jYdWr2nmBxLd16Wi1WA2pHwFKpQdb5NAhqgmuuahLRKLBzhjnGxLlLEzQ9NGB2DAZaPcyXOKfmxsxC4JifbqImIJJSouF2gJ3NI01q7WNoVmqOuT5mbrE22BqtfMk7rjaVIn7n6jaLarfYfrK9ICc6lpHx3SPlSRublN96c8lXw4kJlO9h9nq+xrs5nawuRPTvs9KDtap27MJ8YjluT3cYNvdoq7C/Y7QqDGXaYwpSIYjBqkfyHTGLeg+M0C7SzYAem2Arr2FX1Xu6QHusXyBJDjXpyWaIadZxvxd83L3Bnr/99wjd9Nt59d86215i1Xa3ptk84RLwbA364Tbdxts3Q1i5R7fVKqfpWy041j9ne2UZwCtdgr4q0H/Qzy010lXLGNKvCboHSFWzWfE9XwJuTtzf1PnJpf3SXA5TcP+xTzasnT6az6eccjNvB485RT/i9MfezwHOVNFtVPbWLV6aK2raaNe67JK+kb7p7zSPKXb+TJ88JjOeclEtYpHE7RVhByaqFynucK090tUGGZ0WSuW6gLZYakMzfXZeFl8/R8GMv4D
--------------------------------------------------------------------------------
/12-享元模式/缓存服务器.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/12-享元模式/缓存服务器.png
--------------------------------------------------------------------------------
/12-享元模式/运行动图.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/12-享元模式/运行动图.gif
--------------------------------------------------------------------------------
/13-适配器模式/13-01.plugAdapter.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 适配器模式
3 | * 作者: SHERlocked93
4 | * 功能: 电源适配器例子
5 | */
6 |
7 | var chinaPlug = {
8 | type: '中国插头',
9 | chinaInPlug() {
10 | console.log('开始供电')
11 | }
12 | }
13 |
14 | var japanPlug = {
15 | type: '日本插头',
16 | japanInPlug() {
17 | console.log('开始供电')
18 | }
19 | }
20 |
21 | /* 日本插头电源适配器 */
22 | function japanPlugAdapter(plug) {
23 | return {
24 | chinaInPlug() {
25 | return plug.japanInPlug()
26 | }
27 | }
28 | }
29 |
30 | japanPlugAdapter(japanPlug).chinaInPlug()
31 | // 输出:开始供电
32 |
--------------------------------------------------------------------------------
/13-适配器模式/13-02.ajax2axios demo.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 适配器模式
3 | * 作者: SHERlocked93
4 | * 功能: 运行不起来,是示例代码
5 | */
6 |
7 | /* 适配器 */
8 | function ajax2AxiosAdapter(ajaxOptions) {
9 | return axios({
10 | url: ajaxOptions.url,
11 | method: ajaxOptions.type,
12 | responseType: ajaxOptions.dataType,
13 | data: ajaxOptions.data
14 | })
15 | .then(ajaxOptions.success)
16 | .catch(ajaxOptions.error)
17 | }
18 |
19 | /* 经过适配器包装 */
20 | $.ajax = function(options) {
21 | return ajax2AxiosAdapter(options)
22 | }
23 |
24 | $.ajax({
25 | url: '/demo-url',
26 | type: 'POST',
27 | dataType: 'json',
28 | data: {
29 | name: '张三',
30 | id: '2345'
31 | },
32 | success: function(data) {
33 | console.log('访问成功!')
34 | },
35 | error: function(err) {
36 | console.err('访问失败~')
37 | }
38 | })
39 |
--------------------------------------------------------------------------------
/13-适配器模式/13-03.tree2array demo.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 适配器模式
3 | * 作者: SHERlocked93
4 | * 功能: 形数据结构转换为平铺数据结构
5 | */
6 |
7 | /* 原来的树形结构 */
8 | const oldTreeData = [
9 | {
10 | name: '总部',
11 | place: '一楼',
12 | children: [
13 | { name: '财务部', place: '二楼' },
14 | { name: '生产部', place: '三楼' },
15 | {
16 | name: '开发部', place: '三楼', children: [
17 | {
18 | name: '软件部', place: '四楼', children: [
19 | { name: '后端部', place: '五楼' },
20 | { name: '前端部', place: '七楼' },
21 | { name: '技术支持部', place: '六楼' }]
22 | }, {
23 | name: '硬件部', place: '四楼', children: [
24 | { name: 'DSP部', place: '八楼' },
25 | { name: 'ARM部', place: '二楼' },
26 | { name: '调试部', place: '三楼' }]
27 | }]
28 | }
29 | ]
30 | }
31 | ]
32 |
33 | /* 树形结构平铺 */
34 | function treeDataAdapter(treeData, lastArrayData = []) {
35 | treeData.forEach(item => {
36 | if (item.children) {
37 | treeDataAdapter(item.children, lastArrayData)
38 | }
39 | const { name, place } = item
40 | lastArrayData.push({ name, place })
41 | })
42 | return lastArrayData
43 | }
44 |
45 | treeDataAdapter(oldTreeData)
46 |
47 | // 返回平铺的组织结构
48 |
--------------------------------------------------------------------------------
/13-适配器模式/官网计算属性例子.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Original message: "{{ message }}"
4 |
Computed reversed message: "{{ reversedMessage }}"
5 |
6 |
7 |
8 |
23 |
24 |
27 |
--------------------------------------------------------------------------------
/13-适配器模式/适配器模式.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/13-适配器模式/适配器模式.png
--------------------------------------------------------------------------------
/13-适配器模式/适配器模式.xml:
--------------------------------------------------------------------------------
1 | zVhbc9o6EP41PMLIlo3hEchtzvRMe5JO2/Slo9jCViJbjiwK9NdXsuWLfAsZmubAA9buarXe/fYiJnATH645SqN/WYDpxAbBYQIvJrZtWQtX/ijKUVOAYxeUkJOgoIGacEd+YS2oN4Y7EuBM0wqSYIwKkppEnyUJ9oVBQ5yzvSm2ZTQwCCkKsWGGItz5iOKO2FcSiKigugtY028wCSN9smNpxgPyn0LOdok+LmEJLjgxKrXoE7MIBWzfIMHLCdxwxkTxFB82mCq3mg67GuBWFnOciFM2/JcFKwqfEP5wf5Pa/1ir79fu1HIKNT8R3WlXaGvFsfRN/npYaQETuN5HROC7FPmKu5dwkLRIxFSuLPlYvaWSzQRnT5VDFXtLKN0wyniuGm5d9a0kS07uRbgOUBbl5+Y7WSIaO4uPpGv7MRf4MOgZq/K3hDBmMRb8KEX0BnupvaDRCz2tYl9DYQ50GKMGDKzFXENQwy+sdNeBkA86Fq+Ji9sJAw4kYvWScRGxkCWIXtbUtRmoWuYDY6n24iMW4qjTD+0EawXPiJf02Fp6kB+/aY354l4tZm65vDg0mRfHKvKIi5VKTEnwKcoy4pfkK0LLA3ESlEI65pKi+aAKrnrz8dBKR7Ed97XU19vHOHqmH9OP9+w2W83h/OY4LasK4iEWY54H/VjhmCJBfpqG9MVdb/3EiDSxwpjleTPbsz3gAm9h2a4BuDmUHnUtsHSA/PHcham9sFkrbAGrsvAMrM3fA2s1smow3RtYOgFZGjRNWAETVjX2amT1Q10VmCsUE6pO+oJ5gBKkyfolrGW7KL0HPgdq2evwKd2Djg2BVIErG4Gv3SqR0DabTUt+AcGYvHwoLPizQPY6zYzj5x3ORAfgslkIE48cZ+QXesgFFIa0R6S0u564F5KCKAkTBSkZWyzb0Fo1HSJniJVmxCQI8uSg6AHTdTUaNBte/umB1QD6BrubHoS0wc25pobeSLYP9sIpmMmuZhnBm+qZ4MwS6JgQmnqmArbdZvjcAjeWWg1YfCEZETImZ406LxcMu7/SDBaJTpwHwwSXhi8d6HQmFsvrmVjm4K0GFviuTcSavHI86Y/Jayv5I39yv29j724JYuD4m9vrgP+9SePUgI1Z2UiKVYBSVdjacew6Sw75qWLGh1DdB2dbyvZ+JHvwLCBcVqUfARJoIIHa6TFa+M7KERfYZpI43SSxgdNNEufNkgR0nD6x51R1oixFieH2+fNO3Qxz/0yz3GErKWAt00PunpIvn0L1+7mAm1YnzSs0FsxOTF8obShLi1v2lhxUfvYkTO+NrXW9W63Vt30rPLf1nX6xg3BhIsDuImDRUyUXbwaA7u36f1wl89UnzIl8eTXw/NHSOTLcmrVzuHr9hdI5amUjjcvsaweXUpJm+OVZ4oSEG8ytvkR8p4TzlubY/4YJJ5f1f2fFpFj/NwkvfwM=
--------------------------------------------------------------------------------
/14-装饰者模式/14-01.decoration demo1 es5.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-07-06
3 | * 作者: SHERlocked93
4 | * 功能: 装饰者模式 es5 方式
5 | */
6 |
7 | /* 毛坯房 */
8 | function OriginHouse() {}
9 |
10 | OriginHouse.prototype.getDesc = function() {
11 | console.log('毛坯房')
12 | }
13 |
14 | /* 搬入家具 */
15 | function Furniture(house) {
16 | this.house = house
17 | }
18 |
19 | Furniture.prototype.getDesc = function() {
20 | this.house.getDesc()
21 | console.log('搬入家具')
22 | }
23 |
24 | /* 墙壁刷漆 */
25 | function Painting(house) {
26 | this.house = house
27 | }
28 |
29 | Painting.prototype.getDesc = function() {
30 | this.house.getDesc()
31 | console.log('墙壁刷漆')
32 | }
33 |
34 | var house = new OriginHouse()
35 | house = new Furniture(house)
36 | house = new Painting(house)
37 |
38 | house.getDesc()
39 | // 输出: 毛坯房 搬入家具 墙壁刷漆
40 |
--------------------------------------------------------------------------------
/14-装饰者模式/14-02.decoration demo2 es6.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-07-06
3 | * 作者: SHERlocked93
4 | * 功能: 装饰者模式 es6 方式
5 | */
6 |
7 | /* 毛坯房 */
8 | class OriginHouse {
9 | getDesc() {
10 | console.log('毛坯房')
11 | }
12 | }
13 |
14 | /* 搬入家具 */
15 | class Furniture {
16 | constructor(house) {
17 | this.house = house
18 | }
19 |
20 | getDesc() {
21 | this.house.getDesc()
22 | console.log('搬入家具')
23 | }
24 | }
25 |
26 | /* 墙壁刷漆 */
27 | class Painting {
28 | constructor(house) {
29 | this.house = house
30 | }
31 |
32 | getDesc() {
33 | this.house.getDesc()
34 | console.log('墙壁刷漆')
35 | }
36 | }
37 |
38 | let house = new OriginHouse()
39 | house = new Furniture(house)
40 | house = new Painting(house)
41 |
42 | house.getDesc()
43 | // 输出: 毛坯房 搬入家具 墙壁刷漆
44 |
--------------------------------------------------------------------------------
/14-装饰者模式/14-03.decoration demo3.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-07-06
3 | * 作者: SHERlocked93
4 | * 功能: 装饰者模式 js 方式
5 | */
6 |
7 | /* 毛坯房 */
8 | var originHouse = {
9 | getDesc() {
10 | console.log('毛坯房 ')
11 | }
12 | }
13 |
14 | /* 搬入家具 */
15 | function furniture() {
16 | console.log('搬入家具 ')
17 | }
18 |
19 | /* 墙壁刷漆 */
20 | function painting() {
21 | console.log('墙壁刷漆 ')
22 | }
23 |
24 | // 添加装饰 - 搬入家具
25 | originHouse.getDesc = function() {
26 | var getDesc = originHouse.getDesc
27 | return function() {
28 | furniture()
29 | getDesc()
30 | }
31 | }()
32 |
33 | originHouse.getDesc()
34 | // 输出: 毛坯房 搬入家具
35 |
36 | // 添加装饰 - 墙壁刷漆
37 | originHouse.getDesc = function() {
38 | var getDesc = originHouse.getDesc
39 | return function() {
40 | painting()
41 | getDesc()
42 | }
43 | }()
44 |
45 | originHouse.getDesc()
46 | // 输出: 毛坯房 搬入家具 墙壁刷漆
47 |
48 |
--------------------------------------------------------------------------------
/14-装饰者模式/14-04.decoration demo4.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Title
6 |
7 |
8 | hello
9 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/14-装饰者模式/14-05.decoration demo5.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Title
6 |
7 |
8 | hello
9 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/14-装饰者模式/14-06.decoration in TypeScript demo1.ts:
--------------------------------------------------------------------------------
1 | // 这是一个装饰器工厂——有助于将用户参数传给装饰器声明
2 | function f() {
3 | console.log("f(): evaluated");
4 | return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
5 | console.log("f(): called");
6 | }
7 | }
8 |
9 | function g() {
10 | console.log("g(): evaluated");
11 | return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
12 | console.log("g(): called");
13 | }
14 | }
15 |
16 | class C {
17 | @f()
18 | @g()
19 | method() { }
20 | }
21 |
22 | // f(): evaluated
23 | // g(): evaluated
24 | // g(): called
25 | // f(): called
26 |
--------------------------------------------------------------------------------
/14-装饰者模式/14-07.decoration in TypeScript demo2.ts:
--------------------------------------------------------------------------------
1 | class Greeter {
2 | greeting: string;
3 |
4 | constructor(message: string) {
5 | this.greeting = message;
6 | }
7 |
8 | greet() {
9 | return "Hello, " + this.greeting;
10 | }
11 | }
12 |
13 | for (let key in new Greeter('Jim')) {
14 | console.log(key);
15 | }
16 | // 输出: greeting greet
17 |
--------------------------------------------------------------------------------
/14-装饰者模式/14-08.decoration in TypeScript demo3.ts:
--------------------------------------------------------------------------------
1 | function enumerable(value: boolean) {
2 | return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
3 | descriptor.enumerable = value;
4 | };
5 | }
6 |
7 | class Greeter {
8 | greeting: string;
9 |
10 | constructor(message: string) {
11 | this.greeting = message;
12 | }
13 |
14 | @enumerable(false)
15 | greet() {
16 | return "Hello, " + this.greeting;
17 | }
18 | }
19 |
20 | for (let key in new Greeter('Jim')) {
21 | console.log(key);
22 | }
23 | // 输出: greeting
24 |
--------------------------------------------------------------------------------
/14-装饰者模式/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES5",
4 | "experimentalDecorators": true
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/14-装饰者模式/装饰器模式.drawio:
--------------------------------------------------------------------------------
1 | 7VhNc9sgFPw1PqYjQMj2MXbS9tJpGnemxw6RXiSmSCgYf/XXF2wkGWFP0taJJ23GB8MKPWB33xPSgEzL9QfF6uKTzEAMcJStB+RqgDGKCTF/Ftk4JIrxDskVz3ZY1AEz/hOagQ5d8AzmDttBWkqhee2DqawqSLWHMaXkyh92L0XmATXLwVuGBWYpExAM+8YzXezQER52+EfgeeFmpiO34ZI1Y13cecEyudqDyPWATJWUetcq11MQljyflvdHrrbrUlDpp9ww/v4ZbtXtTVGVm9mX5cNFPXy4cFGWTCzcfr8ylYN2S9abhgYTyzBuOpNVwTXMapbaKyujusEKXQrTQ6Y510r+aKkyu5zcy0o7Xc0SycRNCUrD+uheUMuQsRbIErTamCHuBhw5+htXxa6/6iRCDfHFnjwjhzHnirwN3TFnGo683yASB0QGFBoD1LZ5L2B9aZ1puIAqc82rVLD5nKc+m33uDrDLhZhKIdV2EnI5sb92ZHOlkhW01EOW9839KPF7xNIDvDaYAsE0X/rhD5HtZriR3Ezc6Zok76inLI7HfpC5XKgU3H37dg9C+RYhUW81emv0INBW/Xbjf24I8rghTphTPRdcJ/Z3mlxDMe1pQkiYbTgmoSsQGj1TusWvtG5R7DNJkzPXLRoQeQWpVExLhQIyzcb1IdZ6VWbfjA5igueVLXKGKDD4xNLIzVP20l0oeZaJYzIpuagysNuIfF2Mv07jcUr6Hh+FyoyTUBj8XMKg5JwFpH2MnIDcYewxSykNmG3Z9qpHkyyn53b4rxRnHPWLMx3icxfnJvBrq84E+dWZjtGZqzMav5Vn61/UL88JDqV50fLcBH478P/tgd/TNe6n0tOP+/03B0p6j49nPvDj8F26zVWDJ8Lm5p0yrVy3yvwP2Tsevlzymm73RWWnbPddilz/Ag==
--------------------------------------------------------------------------------
/14-装饰者模式/装饰器模式.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/14-装饰者模式/装饰器模式.png
--------------------------------------------------------------------------------
/15-外观模式/15-01.uav demo1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-07-13
3 | * 作者: SHERlocked93
4 | * 功能: 外观模式 无人机例子
5 | */
6 |
7 |
8 | var uav = {
9 | /**
10 | * 电子调速器
11 | */
12 | diantiao1: {
13 | up() {
14 | console.log('电调1发送指令:电机1增大转速')
15 | uav.dianji1.up()
16 | },
17 | down() {
18 | console.log('电调1发送指令:电机1减小转速')
19 | uav.dianji1.up()
20 | }
21 | },
22 | diantiao2: {
23 | up() {
24 | console.log('电调2发送指令:电机2增大转速')
25 | uav.dianji2.up()
26 | },
27 | down() {
28 | console.log('电调2发送指令:电机2减小转速')
29 | uav.dianji2.down()
30 | }
31 | },
32 | diantiao3: {
33 | up() {
34 | console.log('电调3发送指令:电机3增大转速')
35 | uav.dianji3.up()
36 | },
37 | down() {
38 | console.log('电调3发送指令:电机3减小转速')
39 | uav.dianji3.down()
40 | }
41 | },
42 | diantiao4: {
43 | up() {
44 | console.log('电调4发送指令:电机4增大转速')
45 | uav.dianji4.up()
46 | },
47 | down() {
48 | console.log('电调4发送指令:电机4减小转速')
49 | uav.dianji4.down()
50 | }
51 | },
52 |
53 | /**
54 | * 电机
55 | */
56 | dianji1: {
57 | up() { console.log('电机1增大转速') },
58 | down() { console.log('电机1减小转速') }
59 | },
60 | dianji2: {
61 | up() { console.log('电机2增大转速') },
62 | down() { console.log('电机2减小转速') }
63 | },
64 | dianji3: {
65 | up() { console.log('电机3增大转速') },
66 | down() { console.log('电机3减小转速') }
67 | },
68 | dianji4: {
69 | up() { console.log('电机4增大转速') },
70 | down() { console.log('电机4减小转速') }
71 | },
72 |
73 | controller: {
74 | /**
75 | * 上升
76 | */
77 | up() {
78 | uav.diantiao1.up()
79 | uav.diantiao2.up()
80 | uav.diantiao3.up()
81 | uav.diantiao4.up()
82 | },
83 |
84 | /**
85 | * 前进
86 | */
87 | forward() {
88 | uav.diantiao1.down()
89 | uav.diantiao2.down()
90 | uav.diantiao3.up()
91 | uav.diantiao4.up()
92 | },
93 |
94 | /**
95 | * 下降
96 | */
97 | down() {
98 | uav.diantiao1.down()
99 | uav.diantiao2.down()
100 | uav.diantiao3.down()
101 | uav.diantiao4.down()
102 | },
103 |
104 | /**
105 | * 左转
106 | */
107 | left() {
108 | uav.diantiao1.up()
109 | uav.diantiao2.down()
110 | uav.diantiao3.up()
111 | uav.diantiao4.down()
112 | }
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/15-外观模式/15-02.facade demo1.js:
--------------------------------------------------------------------------------
1 | function domBindEvent(nodes, type, selector, fn) {
2 | if (fn === undefined) {
3 | fn = selector
4 | selector = null
5 | }
6 | // ... 剩下相关逻辑
7 | }
8 |
9 | domBindEvent(nodes, 'click', '#div1', fn)
10 | domBindEvent(nodes, 'click', fn)
11 |
--------------------------------------------------------------------------------
/15-外观模式/15-03.facade demo2.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-07-13
3 | * 作者: SHERlocked93
4 | * 功能: 外观模式 绑定事件
5 | */
6 |
7 |
8 | function addEvent(dom, type, fn) {
9 | if (dom.addEventListener) { // 支持 DOM2 级事件处理方法的浏览器
10 | dom.addEventListener(type, fn, false)
11 | } else if (dom.attachEvent) { // 不支持 DOM2 级但支持 attachEvent
12 | dom.attachEvent('on' + type, fn)
13 | } else {
14 | dom['on' + type] = fn // 都不支持的浏览器
15 | }
16 | }
17 |
18 | const myInput = document.getElementById('myinput')
19 |
20 | addEvent(myInput, 'click', function() {
21 | console.log('绑定 click 事件')
22 | })
23 |
--------------------------------------------------------------------------------
/15-外观模式/15-04.facade demo3.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-07-13
3 | * 作者: SHERlocked93
4 | * 功能: 外观模式 外观方法
5 | */
6 |
7 |
8 | // 移除 DOM 上的事件
9 | function removeEvent(element, type, fn) {
10 | if (element.removeEventListener) {
11 | element.removeEventListener(type, fn, false)
12 | } else if (element.detachEvent) {
13 | element.detachEvent('on' + type, fn)
14 | } else {
15 | element['on' + type] = null
16 | }
17 | }
18 |
19 | // 获取样式
20 | function getStyle(obj, styleName) {
21 | if (window.getComputedStyle) {
22 | var styles = getComputedStyle(obj, null)[styleName]
23 | } else {
24 | var styles = obj.currentStyle[styleName]
25 | }
26 | return styles
27 | }
28 |
29 | // 阻止默认事件
30 | var preventDefault = function(event) {
31 | if (event.preventDefault) {
32 | event.preventDefault()
33 | } else { // IE 下
34 | event.returnValue = false
35 | }
36 | }
37 |
38 | // 阻止时间冒泡
39 | var cancelBubble = function(event) {
40 | if (event.stopPropagation) {
41 | event.stopPropagation()
42 | } else { // IE 下
43 | event.cancelBubble = true
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/15-外观模式/外观模式-无人机模块图.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/15-外观模式/外观模式-无人机模块图.png
--------------------------------------------------------------------------------
/15-外观模式/外观模式.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/15-外观模式/外观模式.png
--------------------------------------------------------------------------------
/16-组合模式/16-01.folder demo1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-07-13
3 | * 作者: SHERlocked93
4 | * 功能: 组合模式 文件夹例子
5 | */
6 |
7 |
8 | var createFolder = function(name) {
9 | return {
10 | name: name,
11 | _children: [],
12 |
13 | /**
14 | * 在文件夹下增加文件或文件夹
15 | * @param fileOrFolder
16 | */
17 | add(fileOrFolder) {
18 | this._children.push(fileOrFolder)
19 | },
20 |
21 | /**
22 | * 扫描方法
23 | * @param cb
24 | */
25 | scan(cb) {
26 | this._children.forEach(function(child) {
27 | child.scan(cb)
28 | })
29 | }
30 | }
31 | }
32 |
33 | var createFile = function(name, size) {
34 | return {
35 | name: name,
36 | size: size,
37 |
38 | /**
39 | * 在文件下增加文件,应报错
40 | */
41 | add() {
42 | throw new Error('文件下面不能再添加文件')
43 | },
44 |
45 | /**
46 | * 执行扫描方法
47 | * @param cb
48 | */
49 | scan(cb) {
50 | cb(this)
51 | }
52 | }
53 | }
54 |
55 | var foldMovies = createFolder('电影')
56 | var foldMarvelMovies = createFolder('漫威英雄电影')
57 | var foldDCMovies = createFolder('DC英雄电影')
58 |
59 | foldMarvelMovies.add(createFile('钢铁侠.mp4', 1.9))
60 | foldMarvelMovies.add(createFile('蜘蛛侠.mp4', 2.1))
61 | foldMarvelMovies.add(createFile('金刚狼.mp4', 2.3))
62 | foldMarvelMovies.add(createFile('黑寡妇.mp4', 1.9))
63 | foldMarvelMovies.add(createFile('美国队长.mp4', 1.4))
64 |
65 | foldDCMovies.add(createFile('蝙蝠侠.mp4', 2.4))
66 | foldDCMovies.add(createFile('超人.mp4', 1.6))
67 |
68 | foldMovies.add(foldMarvelMovies)
69 | foldMovies.add(foldDCMovies)
70 |
71 | console.log('size 大于2G的文件有:')
72 | foldMovies.scan(function(item) {
73 | if (item.size > 2) {
74 | console.log('name:' + item.name + ' size:' + item.size + 'GB')
75 | }
76 | })
77 |
78 | // size 大于2G的文件有:
79 | // name:蜘蛛侠.mp4 size:2.1GB
80 | // name:金刚狼.mp4 size:2.3GB
81 | // name:蝙蝠侠.mp4 size:2.4GB
82 |
--------------------------------------------------------------------------------
/16-组合模式/16-02.folder demo2.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-07-13
3 | * 作者: SHERlocked93
4 | * 功能: 组合模式 文件夹例子
5 | */
6 |
7 | const createFolder = function(name) {
8 | return {
9 | name: name,
10 | _children: [],
11 |
12 | /**
13 | * 在文件夹下增加文件或文件夹
14 | * @param fileOrFolder
15 | */
16 | add(...fileOrFolder) {
17 | this._children.push(...fileOrFolder)
18 | return this
19 | },
20 |
21 | /**
22 | * 扫描方法
23 | * @param cb
24 | */
25 | scan(cb) {
26 | this._children.forEach(child => child.scan(cb))
27 | }
28 | }
29 | }
30 |
31 | const createFile = function(name, size) {
32 | return {
33 | name: name,
34 | size: size,
35 |
36 | /**
37 | * 在文件下增加文件,应报错
38 | */
39 | add() {
40 | throw new Error('文件下面不能再添加文件')
41 | },
42 |
43 | /**
44 | * 执行扫描方法
45 | * @param cb
46 | */
47 | scan(cb) {
48 | cb(this)
49 | }
50 | }
51 | }
52 |
53 | const foldMovies = createFolder('电影')
54 | .add(
55 | createFolder('漫威英雄电影')
56 | .add(createFile('钢铁侠.mp4', 1.9))
57 | .add(createFile('蜘蛛侠.mp4', 2.1))
58 | .add(createFile('金刚狼.mp4', 2.3))
59 | .add(createFile('黑寡妇.mp4', 1.9))
60 | .add(createFile('美国队长.mp4', 1.4)),
61 | createFolder('DC英雄电影')
62 | .add(createFile('蝙蝠侠.mp4', 2.4))
63 | .add(createFile('超人.mp4', 1.6))
64 | )
65 |
66 | console.log('size 大于2G的文件有:')
67 |
68 | foldMovies.scan(item => {
69 | if (item.size > 2) {
70 | console.log(`name:${ item.name } size:${ item.size }GB`)
71 | }
72 | })
73 |
74 | // size 大于2G的文件有:
75 | // name:蜘蛛侠.mp4 size:2.1GB
76 | // name:金刚狼.mp4 size:2.3GB
77 | // name:蝙蝠侠.mp4 size:2.4GB
78 |
--------------------------------------------------------------------------------
/16-组合模式/16-03.folder class demo.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-07-13
3 | * 作者: SHERlocked93
4 | * 功能: 组合模式 文件夹例子
5 | */
6 |
7 | class Folder {
8 | constructor(name, children) {
9 | this.name = name
10 | this.children = children
11 | }
12 |
13 | /**
14 | * 在文件夹下增加文件或文件夹
15 | * @param fileOrFolder
16 | */
17 | add(...fileOrFolder) {
18 | this.children.push(...fileOrFolder)
19 | return this
20 | }
21 |
22 | /**
23 | * 扫描方法
24 | * @param cb
25 | */
26 | scan(cb) {
27 | this.children.forEach(child => child.scan(cb))
28 | }
29 | }
30 |
31 | class File {
32 | constructor(name, size) {
33 | this.name = name
34 | this.size = size
35 | }
36 |
37 | /**
38 | * 在文件下增加文件,应报错
39 | * @param fileOrFolder
40 | */
41 | add(...fileOrFolder) {
42 | throw new Error('文件下面不能再添加文件')
43 | }
44 |
45 | /**
46 | * 执行扫描方法
47 | * @param cb
48 | */
49 | scan(cb) {
50 | cb(this)
51 | }
52 | }
53 |
54 | const foldMovies = new Folder('电影', [
55 | new Folder('漫威英雄电影', [
56 | new File('钢铁侠.mp4', 1.9),
57 | new File('蜘蛛侠.mp4', 2.1),
58 | new File('金刚狼.mp4', 2.3),
59 | new File('黑寡妇.mp4', 1.9),
60 | new File('美国队长.mp4', 1.4)]),
61 | new Folder('DC英雄电影', [
62 | new File('蝙蝠侠.mp4', 2.4),
63 | new File('超人.mp4', 1.6)])
64 | ])
65 |
66 | console.log('size 大于2G的文件有:')
67 |
68 | foldMovies.scan(item => {
69 | if (item.size > 2) {
70 | console.log(`name:${ item.name } size:${ item.size }GB`)
71 | }
72 | })
73 |
74 | // size 大于2G的文件有:
75 | // name:蜘蛛侠.mp4 size:2.1GB
76 | // name:金刚狼.mp4 size:2.3GB
77 | // name:蝙蝠侠.mp4 size:2.4GB
78 |
79 |
--------------------------------------------------------------------------------
/16-组合模式/16-04.create element.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-07-21
3 | * 作者: SHERlocked93
4 | * 功能: 组合模式 快捷创建 DOM 树
5 | */
6 |
7 |
8 | const createElement = ({ tag, attr, children }) => {
9 | const node = tag
10 | ? document.createElement(tag)
11 | : document.createTextNode(attr.text)
12 | tag && Object.keys(attr)
13 | .forEach(key => node.setAttribute(key, attr[key]))
14 | children && children
15 | .forEach(child =>
16 | node.appendChild(createElement.call(null, child)))
17 | return node
18 | }
19 |
20 | createElement({
21 | tag: 'ul',
22 | attr: { id: 'data-list' },
23 | children: [
24 | {
25 | tag: 'li',
26 | attr: { class: 'data-item' },
27 | children: [{ attr: { text: 'li-item 1' } }]
28 | },
29 | {
30 | tag: 'li',
31 | attr: { class: 'data-item' },
32 | children: [{ attr: { text: 'li-item 2' } }]
33 | },
34 | {
35 | tag: 'li',
36 | attr: { class: 'data-item' },
37 | children: [{ attr: { text: 'li-item 3' } }]
38 | }
39 | ]
40 | })
41 |
42 | // 输出:
43 | //
44 | // - li-item 1
45 | // - li-item 2
46 | // - li-item 3
47 | //
48 |
49 |
--------------------------------------------------------------------------------
/16-组合模式/组合模式.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/16-组合模式/组合模式.png
--------------------------------------------------------------------------------
/16-组合模式/组合模式.xml:
--------------------------------------------------------------------------------
1 | 7VhNc5swEP01OjZjJLDhGDt2e2g7mXombXJTQQG1MssIEeP++kpBgAmx67pT06QeH6x90n5o30qrAZHZqnwraZZ8gIgJhEdRicgVwtjBeKL/DLKpkCDwKyCWPKqgUQss+Q9mNWu04BHLLVZBCkAonnXBENKUhaqDUSlh3V12DyLqABmNWScMAyxDKlhv2WceqaRC/XpbBn/HeJxYz55PqokVrddau3lCI1hvQWSOyEwCqGq0KmdMmNx107LYMdvEJVmqDlFI8MfwU+TfXMdZob7CIr8LN2/qLOdqU2+YRXr/Vkwh1X9TCUUaMWNnpCWQKoEYUireA2QadDT4jSm1sezRQoGGErUSdlaHKDdfjP6FV4u31tyjcFV2pI2VciXhe5N3nbLpPaRqQVdcmCU3TEY0pRa23h3fmCm52vKnpds6FD1uvRmhdlZlwmx/Z4YtlEMhQ7YvrbZQqYyZ2rMON3Wgzw+DFdOb13qSCar4QzcOags5bta1ZOuB5ft3uHdeJ/cD8EgG5RG/Th5fyBl2B+W+svtARWE9ofkETafId9HcQ8EI+b4ZXC7QNEBzH00ddNk/921xmPSuE67YMqOP6Vnrtt4thOcJ3WZuF8FciBkIkI9OyXxsfo3BesbWq90Yk4qV+7ns594qYM+rVOzTA49s0163jdwhdk2y1cRJ8Jfows/Q5SFfkzP+b1ny3S5JARmYJHIm6ddHaXCWJnsyf+IOd2A/65M9cIdzD+xw3pAdLuifxlO8do5/tRxZRC+kFsZ/WAtW9Rq4jrC5XtyAXHQvGLd+1dZGqsis3pOaagI5vszc80Nq9+3v4vE/dvt75x7dY4m4zpNDRCZDP3jHZ556PHn4dCxpsf3CWN2V7WdaMv8J
--------------------------------------------------------------------------------
/17-桥接模式/17-01.washer demo1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-07-30
3 | * 作者: SHERlocked93
4 | * 功能: 桥接模式 变频洗衣机
5 | */
6 |
7 | /* 组装洗衣机 */
8 | function Washer(motorType, rollerType, transducerType) {
9 | this.motor = new Motor(motorType)
10 | this.roller = new Roller(rollerType)
11 | this.transducer = new Transducer(transducerType)
12 | }
13 |
14 | Washer.prototype.work = function() {
15 | this.motor.run()
16 | this.roller.run()
17 | this.transducer.run()
18 | }
19 |
20 | /* 电机 */
21 | function Motor(type) {
22 | this.motorType = type + '电机'
23 | }
24 |
25 | Motor.prototype.run = function() {
26 | console.log(this.motorType + '开始工作')
27 | }
28 |
29 | /* 滚筒 */
30 | function Roller(type) {
31 | this.rollerType = type + '滚筒'
32 | }
33 |
34 | Roller.prototype.run = function() {
35 | console.log(this.rollerType + '开始工作')
36 | }
37 |
38 | /* 变频器 */
39 | function Transducer(type) {
40 | this.transducerType = type + '变频器'
41 | }
42 |
43 | Transducer.prototype.run = function() {
44 | console.log(this.transducerType + '开始工作')
45 | }
46 |
47 | var washerA = new Washer('小功率', '直立', '小功率')
48 | washerA.work()
49 |
50 | // 输出:小功率电机开始工作
51 | // 直立滚筒开始工作
52 | // 小功率变频器开始工作
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/17-桥接模式/17-02.washer class demo2.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-07-30
3 | * 作者: SHERlocked93
4 | * 功能: 桥接模式 变频洗衣机
5 | */
6 |
7 | /* 组装洗衣机 */
8 | class Washer {
9 | constructor(motorType, rollerType, transducerType) {
10 | this.motor = new Motor(motorType)
11 | this.roller = new Roller(rollerType)
12 | this.transducer = new Transducer(transducerType)
13 | }
14 |
15 | /* 开始使用 */
16 | work() {
17 | this.motor.run()
18 | this.roller.run()
19 | this.transducer.run()
20 | }
21 | }
22 |
23 | /* 电机 */
24 | class Motor {
25 | constructor(type) {
26 | this.motorType = type + '电机'
27 | }
28 |
29 | run() {
30 | console.log(this.motorType + '开始工作')
31 | }
32 | }
33 |
34 | /* 滚筒 */
35 | class Roller {
36 | constructor(type) {
37 | this.rollerType = type + '滚筒'
38 | }
39 |
40 | run() {
41 | console.log(this.rollerType + '开始工作')
42 | }
43 | }
44 |
45 | /* 变频器 */
46 | class Transducer {
47 | constructor(type) {
48 | this.transducerType = type + '变频器'
49 | }
50 |
51 | run() {
52 | console.log(this.transducerType + '开始工作')
53 | }
54 | }
55 |
56 | const washerA = new Washer('小功率', '直立', '小功率')
57 | washerA.work()
58 |
59 | // 输出:小功率电机开始工作
60 | // 直立滚筒开始工作
61 | // 小功率变频器开始工作
62 |
--------------------------------------------------------------------------------
/17-桥接模式/17-03.bag class demo1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-07-30
3 | * 作者: SHERlocked93
4 | * 功能: 桥接模式 皮包
5 | */
6 |
7 | /* 皮包 */
8 | class Bag {
9 | constructor(type, color) {
10 | this.type = type
11 | this.color = color
12 | }
13 |
14 | /* 展示 */
15 | show() {
16 | console.log(
17 | this.color.show() + this.type.show()
18 | )
19 | }
20 | }
21 |
22 | /* 皮包类型 */
23 | class Type {
24 | constructor(type) {
25 | this.typeType = type
26 | }
27 |
28 | show() {
29 | return this.typeType
30 | }
31 | }
32 |
33 | /* 皮包颜色 */
34 | class Color {
35 | constructor(type) {
36 | this.colorType = type
37 | }
38 |
39 | show() {
40 | return this.colorType
41 | }
42 | }
43 |
44 |
45 | /* 抽象实例化 */
46 | const redColor = new Color('红色')
47 | const walletType = new Type('钱包')
48 | const briefcaseType = new Type('公文包')
49 |
50 | const bagA = new Bag(walletType, redColor)
51 | bagA.show()
52 |
53 | // 输出:红色钱包
54 |
55 | const bagB = new Bag(briefcaseType, redColor)
56 | bagB.show()
57 |
58 | // 输出:红色公文包
59 |
--------------------------------------------------------------------------------
/17-桥接模式/17-04.operate DOM demo1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-07-31
3 | * 作者: SHERlocked93
4 | * 功能: 操作DOM
5 | */
6 |
7 |
8 | var btn = document.getElementById('btn')
9 |
10 | btn.addEventListener('mouseover', function() {
11 | btn.style.setProperty('color', 'blue')
12 | btn.style.setProperty('background-color', 'green')
13 | btn.style.setProperty('transform', 'scale(1.5)')
14 | })
15 |
16 | btn.addEventListener('mouseleave', function() {
17 | btn.style.setProperty('color', 'black')
18 | btn.style.setProperty('background-color', 'lightgray')
19 | btn.style.setProperty('transform', 'scale(1)')
20 | })
21 |
22 | btn.addEventListener('mousedown', function() {
23 | btn.style.setProperty('color', 'red')
24 | btn.style.setProperty('background-color', 'purple')
25 | btn.style.setProperty('transform', 'scale(.5)')
26 | })
27 |
28 | btn.addEventListener('mouseup', function() {
29 | btn.style.setProperty('color', 'black')
30 | btn.style.setProperty('background-color', 'lightgray')
31 | btn.style.setProperty('transform', 'scale(1)')
32 | })
33 |
--------------------------------------------------------------------------------
/17-桥接模式/17-05.operate DOM demo2.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-07-31
3 | * 作者: SHERlocked93
4 | * 功能: 操作DOM
5 | */
6 |
7 |
8 | var btn = document.getElementById('btn')
9 |
10 | /* 设置前景色和背景色 */
11 | function setColor(element, color = 'black', bgc = 'lightgray') {
12 | element.style.setProperty('color', color)
13 | element.style.setProperty('background-color', bgc)
14 | }
15 |
16 | /* 设置尺寸 */
17 | function setSize(element, size = '1') {
18 | element.style.setProperty('transform', `scale(${ size })`)
19 | }
20 |
21 | btn.addEventListener('mouseover', function() {
22 | setColor(btn, 'blue', 'green')
23 | setSize(btn, '1.5')
24 | })
25 |
26 | btn.addEventListener('mouseleave', function() {
27 | setColor(btn)
28 | setSize(btn)
29 | })
30 |
31 | btn.addEventListener('mousedown', function() {
32 | setColor(btn, 'red', 'purple')
33 | setSize(btn, '.5')
34 | })
35 |
36 | btn.addEventListener('mouseup', function() {
37 | setColor(btn)
38 | setSize(btn)
39 | })
40 |
--------------------------------------------------------------------------------
/17-桥接模式/操作DOM.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/17-桥接模式/操作DOM.gif
--------------------------------------------------------------------------------
/17-桥接模式/桥接模式.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/17-桥接模式/桥接模式.png
--------------------------------------------------------------------------------
/17-桥接模式/桥接模式.xml:
--------------------------------------------------------------------------------
1 | 7Zpbc+MmFIB/jR/jkUDXR8dJt53ZnWYm0+n2kUhEoouEinFs99cXSUgWRr5kY1lxGvvB4oAwnO/AOVwmcJ6tv3BUpN9YjOkEWPF6Au8mANiOG8ifUrJREssBtSThJK5l1lbwSP7FTUElXZIYL5SsFgnGqCCFLoxYnuNIaDLEOVvpxZ4ZjTVBgRKsNaMUPEaIYqPYnyQWaS0NgL+V/4pJkqp/dgNYZ2SoKavqXaQoZquOCN5P4JwzJuqnbD3HtFSerpZf9uS27eI4F6e8gP94mfEHaJGQzb7Mvq2cdfx0A1VrXxBdqg6r1opNowHOlnmMy1rsCbxdpUTgxwJFZe5KQpeyVGRUZcdokbZlF4KzH63aZI9vnwmlc0YZr6qG9175lfKEo5jIjjR5OctxWZzlQpmEHah053Wr+kg5oiTJpYziZ9H+705dqqOYC7zeq0K7BSMtGrMMC76RRdQLbli/oWwZWG6dXm0No7XbtGMU0FcFkTLGpK16C0w+KGav4Qc++Z3OD7pQA+gBkx8ITH6eHQ7Ez7YP4Co1w7hIWcJyRL8yViguf2MhNkqvaCmYjlAqg2++q/erxF9lYuo2ybt1N/Nuo1K7sEz6eE3E9+Zf5HOnXpnaVlsmmlrr/uE42Z1Pd6BJHbAlj/AhZanpH/EEiwPlQL8RcEyRIC96O85P1ByAZecfVVIZ82iQe4b0DvYRgNnWqMTglRO7kmEJ/VEpG47ygbN4KSPGXfgyUCvKx2hDiUTOjzvNp9o2vj61AhT9SCqL+X0pZC1YyY9PsWfwcjdBoHk5CPypGaj4junnbGgNpf3wfzjGtFjqjAMOnDqtemMOuHbd84n8gshHnWOhd8XIQ3N9clt9x/ewJ9N3Rh3whoeds6yQzGV3gWUudGSVpFjg4+71+FDVhl13jXq+tWPoaE4VBJ7hUm2nZ+3vgqHUHVxksL378PPNYaV69YGRylCbvYLQ1YB70NerqEejemuHZduMN+B1r3gufQdm0ezDHd8tGHW7AFyzy3xvUdLpzOGozP1P5iMwHzU4apqpbdR7tNrtLlCuWYP3z7I8FKrDoptFHRfNZJGc8QzRbQH5lJS/3TirrVY2s665LmOY3KuOBd5jCAa90AzBmiVINwRz/KGgOgbU3/KFQLnU4sARb4+G9VOT7vHKGXQPQ19Tvg3snk2ly0bAtndI/T378B9I/WGP7V9W+f4h5fdsqX8c5QN/9LWfudbuKN8Zeq4fGwB0T5x6Bpv5gXlvogPAXLp9MABOc+9gPAAHXa+5qDozgH33HUwu+648XJSXa53oLobjFRq8ptOpgUl2WfSxOK7n5gpJJFVUndmVCiQRojOVkZE4pvv8j77Y6tB23GGIeHZf/BS4PUgG2603j0SbIbQYAIy62/MGLPoS4/DW/VlHk2/p7BwDXNgDrpkjzw/ONcC1K8BPcl1yzQqxvbDXt2LsOQgfDp0ZNR/dBij1c7OoFFZuAthBsZY/lYKsn9oigKduETQ3IaTCEaWYMun2MlmwwJxIfZTTrJ73sM34iYuG+93kviuIylBPuH14yNAM13EGywv0KcNxzTnD9nzT8tzX38CQye0t4vr4YXsXG97/Bw==
--------------------------------------------------------------------------------
/18-发布-订阅模式/18-01.adadis demo1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 发布-订阅模式
3 | * 作者: SHERlocked93
4 | * 功能: adadis 售货员例子
5 | */
6 |
7 | const adadisPub = {
8 | adadisBook: [], // adadis售货员的小本本
9 | subShoe(phoneNumber) { // 买家在小本本是登记号码
10 | this.adadisBook.push(phoneNumber)
11 | },
12 | notify() { // 售货员打电话通知小本本上的买家
13 | for (const customer of this.adadisBook) {
14 | customer.update()
15 | }
16 | }
17 | }
18 |
19 | const customer1 = {
20 | phoneNumber: '152xxx',
21 | update() {
22 | console.log(this.phoneNumber + ': 去商场看看')
23 | }
24 | }
25 |
26 | const customer2 = {
27 | phoneNumber: '138yyy',
28 | update() {
29 | console.log(this.phoneNumber + ': 给表弟买双')
30 | }
31 | }
32 |
33 | adadisPub.subShoe(customer1) // 在小本本上留下号码
34 | adadisPub.subShoe(customer2)
35 |
36 | adadisPub.notify() // 打电话通知买家到货了
37 |
38 | // 152xxx: 去商场看看
39 | // 138yyy: 给表弟买双
40 |
--------------------------------------------------------------------------------
/18-发布-订阅模式/18-02.adadis demo2.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 发布-订阅模式
3 | * 作者: SHERlocked93
4 | * 功能: adadis 售货员例子 改进
5 | */
6 |
7 | const adadisPub = {
8 | adadisBook: [], // adadis售货员的小本本
9 | subShoe(customer) { // 买家在小本本是登记号码
10 | if (!this.adadisBook.includes(customer)) // 判重
11 | this.adadisBook.push(customer)
12 | },
13 | unSubShoe(customer) { // 取消订阅
14 | if (!this.adadisBook.includes(customer)) return
15 | const idx = this.adadisBook.indexOf(customer)
16 | this.adadisBook.splice(idx, 1)
17 | },
18 | notify() { // 售货员打电话通知小本本上的买家
19 | for (const customer of this.adadisBook) {
20 | customer.update()
21 | }
22 | }
23 | }
24 |
25 |
26 | const customer1 = {
27 | phoneNumber: '152xxx',
28 | update() {
29 | console.log(this.phoneNumber + ': 去商场看看')
30 | }
31 | }
32 |
33 | const customer2 = {
34 | phoneNumber: '138yyy',
35 | update() {
36 | console.log(this.phoneNumber + ': 给表弟买双')
37 | }
38 | }
39 |
40 | adadisPub.subShoe(customer1) // 在小本本上留下号码
41 | adadisPub.subShoe(customer1)
42 | adadisPub.subShoe(customer2)
43 | adadisPub.unSubShoe(customer1)
44 |
45 | adadisPub.notify() // 打电话通知买家到货了
46 |
47 | // 138yyy: 给表弟买双
48 |
--------------------------------------------------------------------------------
/18-发布-订阅模式/18-03.adadis demo3.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 发布-订阅模式
3 | * 作者: SHERlocked93
4 | * 功能: adadis 售货员例子 再次改进
5 | */
6 |
7 | const adadisPub = {
8 | adadisBook: {}, // adadis售货员的小本本
9 | subShoe(type, customer) { // 买家在小本本是登记号码
10 | if (this.adadisBook[type]) { // 如果小本本上已经有这个type
11 | if (!this.adadisBook[type].includes(customer)) // 判重
12 | this.adadisBook[type].push(customer)
13 | } else this.adadisBook[type] = [customer]
14 | },
15 | unSubShoe(type, customer) { // 取消订阅
16 | if (!this.adadisBook[type] ||
17 | !this.adadisBook[type].includes(customer)) return
18 | const idx = this.adadisBook[type].indexOf(customer)
19 | this.adadisBook[type].splice(idx, 1)
20 | },
21 | notify(type) { // 售货员打电话通知小本本上的买家
22 | if (!this.adadisBook[type]) return
23 | this.adadisBook[type].forEach(customer =>
24 | customer.update(type)
25 | )
26 | }
27 | }
28 |
29 | const customer1 = {
30 | phoneNumber: '152xxx',
31 | update(type) {
32 | console.log(this.phoneNumber + ': 去商场看看' + type)
33 | }
34 | }
35 |
36 | const customer2 = {
37 | phoneNumber: '138yyy',
38 | update(type) {
39 | console.log(this.phoneNumber + ': 给表弟买双' + type)
40 | }
41 | }
42 |
43 | adadisPub.subShoe('运动鞋', customer1) // 订阅运动鞋
44 | adadisPub.subShoe('运动鞋', customer1)
45 | adadisPub.subShoe('运动鞋', customer2)
46 | adadisPub.subShoe('帆布鞋', customer1) // 订阅帆布鞋
47 |
48 | adadisPub.notify('运动鞋') // 打电话通知买家运动鞋到货了
49 |
50 | // 152xxx: 去商场看看运动鞋
51 | // 138yyy: 给表弟买双运动鞋
52 |
--------------------------------------------------------------------------------
/18-发布-订阅模式/18-04.pub-sub IIFE.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 发布-订阅模式
3 | * 作者: SHERlocked93
4 | * 功能: IIFE 版发布订阅模式实现
5 | */
6 |
7 | const Publisher = (function() {
8 | const _subsMap = {} // 存储订阅者
9 | return {
10 | /**
11 | * 消息订阅
12 | * @param type 消息类型
13 | * @param cb 消息回调
14 | */
15 | subscribe(type, cb) {
16 | if (_subsMap[type]) {
17 | if (!_subsMap[type].includes(cb))
18 | _subsMap[type].push(cb)
19 | } else _subsMap[type] = [cb]
20 | },
21 | /**
22 | * 消息退订
23 | * @param type 消息类型
24 | * @param cb 消息回调
25 | */
26 | unsubscribe(type, cb) {
27 | if (!_subsMap[type] ||
28 | !_subsMap[type].includes(cb)) return
29 | const idx = _subsMap[type].indexOf(cb)
30 | _subsMap[type].splice(idx, 1)
31 | },
32 | /**
33 | * 消息发布
34 | * @param type 消息类型
35 | * @param payload 回调参数
36 | */
37 | notify(type, ...payload) {
38 | if (!_subsMap[type]) return
39 | _subsMap[type].forEach(cb => cb(...payload))
40 | }
41 | }
42 | })()
43 |
44 | Publisher.subscribe('运动鞋', message => console.log('152xxx' + message)) // 订阅运动鞋
45 | Publisher.subscribe('运动鞋', message => console.log('138yyy' + message))
46 | Publisher.subscribe('帆布鞋', message => console.log('139zzz' + message)) // 订阅帆布鞋
47 |
48 | Publisher.notify('运动鞋', ' 运动鞋到货了 ~') // 打电话通知买家运动鞋消息
49 | Publisher.notify('帆布鞋', ' 帆布鞋售罄了 T.T') // 打电话通知买家帆布鞋消息
50 |
51 | // 输出: 152xxx 运动鞋到货了 ~
52 | // 输出: 138yyy 运动鞋到货了 ~
53 | // 输出: 139zzz 帆布鞋售罄了 T.T
54 |
--------------------------------------------------------------------------------
/18-发布-订阅模式/18-05.pub-sub class.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 发布-订阅模式
3 | * 作者: SHERlocked93
4 | * 功能: es6 的 class 版发布订阅模式实现
5 | */
6 |
7 | class Publisher {
8 | constructor() {
9 | this._subsMap = {} // 存储订阅者
10 | }
11 |
12 | /**
13 | * 消息订阅
14 | * @param type 消息类型
15 | * @param cb 消息回调
16 | */
17 | subscribe(type, cb) {
18 | if (this._subsMap[type]) {
19 | if (!this._subsMap[type].includes(cb))
20 | this._subsMap[type].push(cb)
21 | } else this._subsMap[type] = [cb]
22 | }
23 |
24 | /**
25 | * 消息退订
26 | * @param type 消息类型
27 | * @param cb 消息回调
28 | */
29 | unsubscribe(type, cb) {
30 | if (!this._subsMap[type] ||
31 | !this._subsMap[type].includes(cb)) return
32 | const idx = this._subsMap[type].indexOf(cb)
33 | this._subsMap[type].splice(idx, 1)
34 | }
35 |
36 | /**
37 | * 消息发布
38 | * @param type 消息类型
39 | * @param payload 回调参数
40 | */
41 | notify(type, ...payload) {
42 | if (!this._subsMap[type]) return
43 | this._subsMap[type].forEach(cb => cb(...payload))
44 | }
45 | }
46 |
47 | const adadis = new Publisher()
48 |
49 | adadis.subscribe('运动鞋', message => console.log('152xxx' + message)) // 订阅运动鞋
50 | adadis.subscribe('运动鞋', message => console.log('138yyy' + message))
51 | adadis.subscribe('帆布鞋', message => console.log('139zzz' + message)) // 订阅帆布鞋
52 |
53 | adadis.notify('运动鞋', ' 运动鞋到货了 ~') // 打电话通知买家运动鞋消息
54 | adadis.notify('帆布鞋', ' 帆布鞋售罄了 T.T') // 打电话通知买家帆布鞋消息
55 |
56 | // 输出: 152xxx 运动鞋到货了 ~
57 | // 输出: 138yyy 运动鞋到货了 ~
58 | // 输出: 139zzz 帆布鞋售罄了 T.T
59 |
--------------------------------------------------------------------------------
/18-发布-订阅模式/18-06.pub-sub jquery.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-07-16
3 | * 作者: SHERlocked93
4 | * 功能: 使用 jq 提供的api实现发布订阅
5 | */
6 |
7 |
8 | function eventHandler() {
9 | console.log('自定义方法')
10 | }
11 |
12 | /* ---- 事件订阅 ---- */
13 | $('#app').on('myevent', eventHandler)
14 | /* 发布 */
15 | $('#app').trigger('myevent')
16 |
17 | // 输出:自定义方法
18 |
19 |
20 | /* ---- 取消订阅 ---- */
21 | $('#app').off('myevent')
22 | $('#app').trigger('myevent')
23 |
24 | // 没有输出
25 |
--------------------------------------------------------------------------------
/18-发布-订阅模式/18-07.pub-sub native.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-07-16
3 | * 作者: SHERlocked93
4 | * 功能: 使用浏览器原生方法实现发布订阅
5 | */
6 |
7 |
8 | // 输出:自定义方法
9 | function eventHandler(dom) {
10 | console.log('自定义方法', dom)
11 | }
12 |
13 | var app = document.getElementById('app')
14 |
15 | /* ---- 事件订阅 ---- */
16 | app.addEventListener('myevent', eventHandler)
17 | /* 发布 */
18 | app.dispatchEvent(new Event('myevent'))
19 |
20 | // 输出:自定义方法+DOM
21 |
22 |
23 | /* ---- 取消订阅 ---- */
24 | app.removeEventListener('myevent', eventHandler)
25 | app.dispatchEvent(new Event('myevent'))
26 |
27 | // 没有输出
28 |
--------------------------------------------------------------------------------
/18-发布-订阅模式/发布-订阅模式 概略图.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/18-发布-订阅模式/发布-订阅模式 概略图.png
--------------------------------------------------------------------------------
/18-发布-订阅模式/发布-订阅模式-adadis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/18-发布-订阅模式/发布-订阅模式-adadis.png
--------------------------------------------------------------------------------
/18-发布-订阅模式/发布-订阅模式.xml:
--------------------------------------------------------------------------------
1 | 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
--------------------------------------------------------------------------------
/19-策略模式/19-01.priceclac.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 策略模式
3 | * 作者: SHERlocked93
4 | * 功能: 商品打折的例子
5 | */
6 |
7 | /**
8 | * 计算总售价
9 | * @param discountType 折扣类型
10 | * @param price
11 | * @return {number}
12 | */
13 | function priceCalculate(discountType, price) {
14 | if (discountType === 'minus100_30') { // 满100减30
15 | return price - Math.floor(price / 100) * 30
16 | }
17 | if (discountType === 'minus200_80') { // 满200减80
18 | return price - Math.floor(price / 200) * 80
19 | }
20 | if (discountType === 'percent80') { // 8折
21 | return price * 0.8
22 | }
23 | }
24 |
25 | priceCalculate('minus100_30', 270)
26 | priceCalculate('percent80', 250)
27 |
28 | // 输出: 210
29 | // 输出: 200
30 |
--------------------------------------------------------------------------------
/19-策略模式/19-02.priceclac pro1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 策略模式
3 | * 作者: SHERlocked93
4 | * 功能: 商品打折的例子 改进
5 | */
6 |
7 | /* 售价计算方式 */
8 | const DiscountMap = {
9 | minus100_30: function(price) { // 满100减30
10 | return price - Math.floor(price / 100) * 30
11 | },
12 | minus200_80: function(price) { // 满200减80
13 | return price - Math.floor(price / 200) * 80
14 | },
15 | percent80: function(price) { // 8折
16 | return price * 0.8
17 | }
18 | }
19 |
20 | /**
21 | * 计算总售价
22 | * @param discountType 折扣类型
23 | * @param price
24 | * @return {number}
25 | */
26 | function priceCalculate(discountType, price) {
27 | return DiscountMap[discountType] && DiscountMap[discountType](price)
28 | }
29 |
30 | priceCalculate('minus100_30', 270)
31 | priceCalculate('percent80', 250)
32 |
33 | // 输出: 210
34 | // 输出: 200
35 |
--------------------------------------------------------------------------------
/19-策略模式/19-03.priceclac pro1 IIFE.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 策略模式
3 | * 作者: SHERlocked93
4 | * 功能: 商品打折的例子 改进
5 | */
6 |
7 | /**
8 | * 计算总售价
9 | */
10 | const PriceCalculate = (function() {
11 | /* 售价计算方式 */
12 | const DiscountMap = {
13 | minus100_30: price => price - Math.floor(price / 100) * 30, // 满100减30
14 | minus200_80: price => price - Math.floor(price / 200) * 80, // 满200减80
15 | percent80: price => price * 0.8 // 8折
16 | }
17 |
18 | return {
19 | priceClac: function(discountType, price) {
20 | return DiscountMap[discountType] && DiscountMap[discountType](price)
21 | },
22 | addStrategy: function(discountType, fn) { // 添加新的策略
23 | if (DiscountMap[discountType]) return // 如果已有这个策略
24 | DiscountMap[discountType] = fn
25 | }
26 | }
27 | })()
28 |
29 | PriceCalculate.priceClac('minus100_30', 270)
30 |
31 | PriceCalculate.addStrategy('minus150_40', price => price - Math.floor(price / 150) * 40
32 | )
33 | PriceCalculate.priceClac('minus150_40', 270)
34 |
35 | // 输出: 210
36 | // 输出: 230
37 |
--------------------------------------------------------------------------------
/19-策略模式/19-04.strategy.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 策略模式
3 | * 作者: SHERlocked93
4 | * 功能: 通用实现
5 | */
6 |
7 | const StrategyMap = {}
8 |
9 | function context(type, ...rest) {
10 | return StrategyMap[type] && StrategyMap[type](...rest)
11 | }
12 |
13 | StrategyMap.minus100_30 = price => price - Math.floor(price / 100) * 30
14 |
15 | context('minus100_30', 270)
16 |
17 | // 输出: 210
18 |
--------------------------------------------------------------------------------
/19-策略模式/19-05.strategy demo1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 策略模式
3 | * 作者: SHERlocked93
4 | * 功能: 实战
5 | */
6 |
7 | import * as Utils from './StrategyMap.js'
8 |
9 | context('minus100_30', 270)
10 |
11 | // 输出: 210
12 |
--------------------------------------------------------------------------------
/19-策略模式/19-06.ElTableDemo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
10 |
11 |
12 |
13 |
14 |
29 |
30 |
33 |
--------------------------------------------------------------------------------
/19-策略模式/19-07.ElFormDemo.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
48 |
49 |
52 |
--------------------------------------------------------------------------------
/19-策略模式/strategyContext.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 作者: SHERlocked93
3 | * 功能: 过滤器策略
4 | */
5 |
6 | export const StrategyMap = {
7 | /**
8 | * 功能: 将文件大小(bit)转化为 KB
9 | * @param val
10 | * @returns {string}
11 | */
12 | bitToKB: val => {
13 | const num = Number(val)
14 | return isNaN(num) ? val : (num / 1024).toFixed(0) + 'KB'
15 | },
16 | /**
17 | * 功能: 将文件大小(bit)转化为 MB
18 | * @param val
19 | * @returns {string}
20 | */
21 | bitToMB: val => {
22 | const num = Number(val)
23 | return isNaN(num) ? val : (num / 1024 / 1024).toFixed(1) + 'MB'
24 | }
25 | }
26 |
27 | /**
28 | * 生成el表单 formatter
29 | * @param type strategy
30 | * @param rowKey
31 | */
32 | const strategyContext = (type, rowKey) => (row, column, cellValue, index) => StrategyMap[type](row[rowKey])
33 |
34 | export default strategyContext
35 |
36 |
--------------------------------------------------------------------------------
/19-策略模式/utils/index.js:
--------------------------------------------------------------------------------
1 | import * as Validates from './validates'
2 |
3 | /**
4 | * 生成表格自定义校验函数
5 | * @param key validate的key
6 | * @param msg 校验信息
7 | * @return {Function}
8 | */
9 | export const formValidateGene = (key, msg) => (rule, value, cb) => {
10 | if (Validates[key](value)) {
11 | cb()
12 | } else {
13 | cb(new Error(msg))
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/19-策略模式/utils/validates.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-06-24
3 | * 作者: SHERlocked93
4 | * 功能: 自定义表单验证
5 | */
6 |
7 |
8 | /**
9 | * 姓名校验 由2-10位汉字组成
10 | * @param str
11 | * @returns {boolean}
12 | */
13 | export function validateUsername(str) {
14 | const reg = /^[\u4e00-\u9fa5]{2,10}$/
15 | return reg.test(str)
16 | }
17 |
18 | /**
19 | * 手机号校验 由以1开头的11位数字组成
20 | * @param str
21 | * @returns {boolean}
22 | */
23 | export function validateMobile(str) {
24 | const reg = /^1\d{10}$/
25 | return reg.test(str)
26 | }
27 |
28 | /**
29 | * 邮箱校验
30 | * @param str
31 | * @returns {boolean}
32 | */
33 | export function validateEmail(str) {
34 | const reg = /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/
35 | return reg.test(str)
36 | }
37 |
--------------------------------------------------------------------------------
/19-策略模式/策略模式.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/19-策略模式/策略模式.png
--------------------------------------------------------------------------------
/19-策略模式/策略模式.xml:
--------------------------------------------------------------------------------
1 | 7Vpdb6M4FP01kXYfEoENhjy2SdNqNaOumqoz3ZeVAw7QGpwxzld//drBBAiQptMmmR31pcHX1/blnuPr46QdOIhX1xzPwq/MJ7QDDH/VgcMOAAhZ8q8yrLXB7WeGgEd+ZjIKwzh6IZnRtLV1Hvkk1bbMJBijIppVjR5LEuKJig1zzpZVtymjfsUwwwGphKEMYw9TUnP7FvkizKy2Cwv7DYmCUK9smbpjgr3ngLN5opdLWEKynhjns+gV0xD7bFkywasOHHDGRPYUrwaEqqRWEzZq6d1GzEkiDhnwEn9ZvCxuH9PV5P4Z/Nvl99fDbv4eC0znOhU6WrHOc6Peb1ZfTQewIFyQVRNIeELJ7utK/hAWE8HX0k+PAlCTR3MHuLq9LJAAjiZKWEIB5o5Yox9s5y7yIB90Kt6SFuP1tGxQJ2oWowMvl2EkyHiGPdW7lHtE2kIRy1WHpnxMBWfPW2rJZFxOWSJGOI6oeusHwn2cYG3W28NEsk3xhNDLLcsGjDIu+zY8k94RpbmpA+AVGo0Gg+1yO85MRhcJtZyrIvZxGm7CV/HV4d1Pl13Q6+CeETyzBt5AZpWsRAcgKpe/nPAKlOjHXG3CTe676Sb5F9IBwNmq6JRPgdhmqsSDzcQNYO+BSpswjYJENimZqhlUUiNZki60OY58Xy3SyK0q+ypYvkKZV3kHYJ0sH88PvdmNngstxwXIcFHfRnZeQ0r0MS1Upw+we4ZVHgmPxSZwaIVsAf6IldN2wK9WOd3PwrmXRb9y4ezXsBsLjgUJyPqrxOWzeB65eP4cR/Jhx66OT/zZ/mcaO+O+ERuWN7i79nkX1vVjr9c7AsyezB3h7wO6BBMyGmvLxyOley2nZ1dKNTTcHoIFSE6tcPeNOq6W2XNg39yOM98Pq/gLPtIbFw3j0ehBoNQDzn23XrSJL+9Lusm4CFnAEkyvCutOrgufL4zNNOhPRIi1RgDPBatSQuacr7/r8ZvGo2rIxOnmcFXuHK51qw1GFXLldG04g1M25572+nb3FIc/6O3s9pHdpRcIopt1N7+MYh6QvZRoOak5oVhEi2og78FrX5SlXfgQpZGQG+ldh+8B5e7QfdSmeVp3jFndL1YuAsvC0GnYIsg4VqlrUDbZiZjOcJKfcPrEXOd9cqlyd9MQ+YljlflkkqoPs3Xs/xVLZParxQ/VdarZWO+OBaZ1KjDBbw+mZZ0bTPtUYMLfHkwbnBDMRunRXmZVQg65ephIXT0y4V36grbrZcpSufBg8gewbeUFBuq2Un3+s35z8ULGUlLCP4vmIPzPqoXIKhLf81nlc2ke2SqmUY18loYb7lvFVCO2DWKq/aht5WzX6Bl2Ln01b7V8Plht6cn/ZtGGU7kLm05TGdkuh7cx/Dytrb2KWl92zkabCuAfw6Ez0MY6kQRvDNL+BPjoANvnBNj5BPj4hb+l8p8G4fotukkUpq/pyDNqwYafFGpwtZ6r21tZrgXtfl0L5tOWtWDffjMgsln88p2dscX/FcCr/wA=
--------------------------------------------------------------------------------
/20-状态模式/20-01.trafficlight demo1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-08-06
3 | * 作者: SHERlocked93
4 | * 功能: 红绿灯例子 反例
5 | */
6 |
7 |
8 | var trafficLight = (function() {
9 | var state = '绿灯' // 闭包缓存状态
10 |
11 | return {
12 | /* 设置交通灯状态 */
13 | setState: function(target) {
14 | if (target === '红灯') {
15 | state = '红灯'
16 | console.log('交通灯颜色变为 红色,行人通行 & 车辆等待')
17 | } else if (target === '黄灯') {
18 | state = '黄灯'
19 | console.log('交通灯颜色变为 黄色,行人等待 & 车辆等待')
20 | } else if (target === '绿灯') {
21 | state = '绿灯'
22 | console.log('交通灯颜色变为 绿色,行人等待 & 车辆通行')
23 | } else {
24 | console.error('交通灯还有这颜色?')
25 | }
26 | },
27 |
28 | /* 获取交通灯状态 */
29 | getState: function() {
30 | return state
31 | }
32 | }
33 | })()
34 |
35 | trafficLight.setState('红灯') // 输出: 交通灯颜色变为 红色,行人通行 & 车辆等待
36 | trafficLight.setState('黄灯') // 输出: 交通灯颜色变为 黄色,行人等待 & 车辆等待
37 | trafficLight.setState('绿灯') // 输出: 交通灯颜色变为 绿色,行人等待 & 车辆通行
38 |
39 | trafficLight.setState('紫灯') // 输出: 交通灯还有这颜色?
40 |
--------------------------------------------------------------------------------
/20-状态模式/20-02.trafficlight demo2.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-08-06
3 | * 作者: SHERlocked93
4 | * 功能: 红绿灯例子 状态模式优化 es5
5 | */
6 |
7 |
8 | /* 抽象状态类 */
9 | var AbstractState = function() {}
10 |
11 | /* 抽象方法 */
12 | AbstractState.prototype.employ = function() {
13 | throw new Error('抽象方法不能调用!')
14 | }
15 |
16 | /* 交通灯状态类 */
17 | var State = function(name, desc) {
18 | this.color = { name, desc }
19 | }
20 |
21 | State.prototype = new AbstractState()
22 | State.prototype.employ = function(trafficLight) {
23 | console.log('交通灯颜色变为 ' + this.color.name + ',' + this.color.desc)
24 | trafficLight.setState(this)
25 | }
26 |
27 | /* 交通灯类 */
28 | var TrafficLight = function() {
29 | this.state = null
30 | }
31 |
32 | /* 获取交通灯状态 */
33 | TrafficLight.prototype.getState = function() {
34 | return this.state
35 | }
36 |
37 | /* 设置交通灯状态 */
38 | TrafficLight.prototype.setState = function(state) {
39 | this.state = state
40 | }
41 |
42 | var trafficLight = new TrafficLight()
43 |
44 | var redState = new State('红色', '行人等待 & 车辆等待')
45 | var greenState = new State('绿色', '行人等待 & 车辆通行')
46 | var yellowState = new State('黄色', '行人等待 & 车辆等待')
47 |
48 | redState.employ(trafficLight) // 输出: 交通灯颜色变为 红色,行人通行 & 车辆等待
49 | yellowState.employ(trafficLight) // 输出: 交通灯颜色变为 黄色,行人等待 & 车辆等待
50 | greenState.employ(trafficLight) // 输出: 交通灯颜色变为 绿色,行人等待 & 车辆通行
51 |
52 |
--------------------------------------------------------------------------------
/20-状态模式/20-03.trafficlight demo3.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-08-06
3 | * 作者: SHERlocked93
4 | * 功能: 红绿灯例子, ES6形式
5 | */
6 |
7 |
8 | /* 抽象状态类 */
9 | class AbstractState {
10 | constructor() {
11 | if (new.target === AbstractState) {
12 | throw new Error('抽象类不能直接实例化!')
13 | }
14 | }
15 |
16 | /* 抽象方法 */
17 | employ() {
18 | throw new Error('抽象方法不能调用!')
19 | }
20 | }
21 |
22 | /* 交通灯类 */
23 | class State extends AbstractState {
24 | constructor(name, desc) {
25 | super()
26 | this.color = { name, desc }
27 | }
28 |
29 | /* 覆盖抽象方法 */
30 | employ(trafficLight) {
31 | console.log('交通灯颜色变为 ' + this.color.name + ',' + this.color.desc)
32 | trafficLight.setState(this)
33 | }
34 | }
35 |
36 | /* 交通灯类 */
37 | class TrafficLight {
38 | constructor() {
39 | this.state = null
40 | }
41 |
42 | /* 获取交通灯状态 */
43 | getState() {
44 | return this.state
45 | }
46 |
47 | /* 设置交通灯状态 */
48 | setState(state) {
49 | this.state = state
50 | }
51 | }
52 |
53 | const trafficLight = new TrafficLight()
54 |
55 | const redState = new State('红色', '行人等待 & 车辆等待')
56 | const greenState = new State('绿色', '行人等待 & 车辆通行')
57 | const yellowState = new State('黄色', '行人等待 & 车辆等待')
58 |
59 | redState.employ(trafficLight) // 输出: 交通灯颜色变为 红色,行人通行 & 车辆等待
60 | yellowState.employ(trafficLight) // 输出: 交通灯颜色变为 黄色,行人等待 & 车辆等待
61 | greenState.employ(trafficLight) // 输出: 交通灯颜色变为 绿色,行人等待 & 车辆通行
62 |
63 | const blueState = new State('蓝色', '行人倒立 & 车辆飞起')
64 | blueState.employ(trafficLight) // 输出: 交通灯颜色变为 蓝色,行人倒立 & 车辆飞起
65 |
--------------------------------------------------------------------------------
/20-状态模式/20-04.trafficlight demo4.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-08-06
3 | * 作者: SHERlocked93
4 | * 功能: 红绿灯例子 引入状态类,并且增加状态机切换逻辑
5 | */
6 |
7 |
8 | /* 抽象状态类 */
9 | class AbstractState {
10 | constructor() {
11 | if (new.target === AbstractState) {
12 | throw new Error('抽象类不能直接实例化!')
13 | }
14 | }
15 |
16 | /* 抽象方法 */
17 | employ() {
18 | throw new Error('抽象方法不能调用!')
19 | }
20 |
21 | changeState() {
22 | throw new Error('抽象方法不能调用!')
23 | }
24 | }
25 |
26 | /* 交通灯类-红灯 */
27 | class RedState extends AbstractState {
28 | constructor() {
29 | super()
30 | this.colorState = '红色'
31 | }
32 |
33 | /* 覆盖抽象方法 */
34 | employ() {
35 | console.log('交通灯颜色变为 ' + this.colorState + ',行人通行 & 车辆等待')
36 | const redDom = document.getElementById('color-red')
37 | redDom.click()
38 | }
39 |
40 | changeState(trafficLight) {
41 | trafficLight.setState(trafficLight.yellowState)
42 | }
43 | }
44 |
45 | /* 交通灯类-绿灯 */
46 | class GreenState extends AbstractState {
47 | constructor() {
48 | super()
49 | this.colorState = '绿色'
50 | }
51 |
52 | /* 覆盖抽象方法 */
53 | employ() {
54 | console.log('交通灯颜色变为 ' + this.colorState + ',行人等待 & 车辆通行')
55 | const greenDom = document.getElementById('color-green')
56 | greenDom.click()
57 | }
58 |
59 | changeState(trafficLight) {
60 | trafficLight.setState(trafficLight.redState)
61 | }
62 | }
63 |
64 | /* 交通灯类-黄灯 */
65 | class YellowState extends AbstractState {
66 | constructor() {
67 | super()
68 | this.colorState = '黄色'
69 | }
70 |
71 | /* 覆盖抽象方法 */
72 | employ() {
73 | console.log('交通灯颜色变为 ' + this.colorState + ',行人等待 & 车辆等待')
74 | const yellowDom = document.getElementById('color-yellow')
75 | yellowDom.click()
76 | }
77 |
78 | changeState(trafficLight) {
79 | trafficLight.setState(trafficLight.greenState)
80 | }
81 | }
82 |
83 | /* 交通灯类 */
84 | class TrafficLight {
85 | constructor() {
86 | this.redState = new RedState()
87 | this.greenState = new GreenState()
88 | this.yellowState = new YellowState()
89 |
90 | this.state = this.greenState
91 | }
92 |
93 | /* 设置交通灯状态 */
94 | setState(state) {
95 | state.employ(this)
96 | this.state = state
97 | }
98 |
99 | changeState() {
100 | this.state.changeState(this)
101 | }
102 | }
103 |
104 |
105 | const trafficLight = new TrafficLight()
106 |
107 | trafficLight.changeState() // 输出: 交通灯颜色变为 红色,行人通行 & 车辆等待
108 | trafficLight.changeState() // 输出: 交通灯颜色变为 黄色,行人等待 & 车辆等待
109 | trafficLight.changeState() // 输出: 交通灯颜色变为 绿色,行人等待 & 车辆通行
110 |
--------------------------------------------------------------------------------
/20-状态模式/状态模式-红绿灯.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/20-状态模式/状态模式-红绿灯.gif
--------------------------------------------------------------------------------
/20-状态模式/状态模式-红绿灯.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/20-状态模式/状态模式-红绿灯.png
--------------------------------------------------------------------------------
/20-状态模式/状态模式.xml:
--------------------------------------------------------------------------------
1 | 7Vhtj5s4EP41/tgVBgzmI2FDK7U9rbTS3bXf3OBN2AKOHGeT3K+/MZgXB5Km20RtdaeNtPbDMJiZ5xmPQV5S7t9Ktl59FBkvkOtke+TdI9fFbuTBP40cDOL4boMsZZ41mNMDj/k/vDU06DbP+MZgDaSEKFS+tsGFqCq+UBbGpBQ72+xJFJkFrNmSW8vQwOOCFXxk9leeqVWDUjfs8Xc8X67Mkwk1L1yy1tb43axYJnYDyJsjL5FCqGZU7hNe6ODZYUlPXO3WJXmlLrnhAfMwzT89f95LEb48J39U79WboPHywoqteV80D9EsRnE9oBjFKZoTPYgSNE/RLEEUBhTN7lEc1IM5ovUgnqM4qge4tvG1H/g1b68ObUQV38OCZytVFgBgGG6UFF95IgohAalEBZazp7wojiBW5MsKpgV/0h5euFQ5ZCo2cJlnmX7IbLfKFX9cs4V+4g6ICZgU2yrjOhaOdi4qlbIyLzQt/+QyYxUzsKEgpjA30YHn8P3JsOMumaACLkqu5AFMzA2BSb/hvxeakO96MuHIb7DVgEgtbZjh77Lz3OcYBibN35Fy1x9lhGdAeTPlxRexm/fAIHA6Vc/bcm0i5MNUSLUSS1Gx4oMQ69aGK3UwRmyrBEC1V5i2KbPzD6GUh791au6I0wGfAHjj3DkObZH7vUlfMzsMZw9c5hAgLg24UUyqWBeAnj81luY6XubGrLX4UojF1wYyBmNiItcL5vqvu9JWBPq9lNIRP08oSJDYygU/k0lqyiGTS67O2GFnmqGSF0zlL/ZCrs43Ol1iZmiWDkoMDKBYQB0JEHU0eMxRKJ9rPdyWRSpZeUrmA1a1CsM41BdabbnRKH3uRJ5OpXNQlYAPSZKmSXKdSuF7nlUqMCWjUuGSYFwqsBfdKHfRRbnrKv757aGxifQmoRM9MD7aMMBzfI9oNLEV/bf3Ep+EFkNgN5nYTMiYIX54I4K0XZrFkEgzhPq/v7rT9HbqJo77s9WN8YXJM2oEfVKdvx45I3iCIvdb8ia1Mflf1TYzAjxmhuNNqPpWWzaeOBac6xk3fFnCyw67xonWapTOV3RPXaeoG0NstYrOnR8Fr+kUj1raSztAvs9V07P6ITVzu2UFoF+HnhwGk+NVXLEvJBf2hXSalgPaEWfMuha7uHs0T3gQObxIx3rX8e2DESa2i+Y1zV3Dc+2RI4Kp7aj95NA6auIwcgT0ZIeB2VobbE4vGBP7OS7xj4TWeOxl18X0Bw5r54V3m8Pa9MnMD4dqw3eOi1+jtl/1XDZxQm0VXis6HEi8KzU/S+Ft2/VNiZNpif+gdnGELSn49Ehyl2oXE9dyFARHXz2upV0/sLfYEN9eu2Siuxp/W/ttW+MkuVZr7NnJ8fANO2OY9p9cm0z3H669+b8=
--------------------------------------------------------------------------------
/21-模板方法模式/21-01.coffee demo1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 模板方法模式
3 | * 作者: SHERlocked93
4 | * 功能: 咖啡厅例子 使用原型方式
5 | */
6 |
7 | /* 饮料类,父类 */
8 | var Beverage = function() {
9 | if (new.target === Beverage) {
10 | throw new Error('抽象类不能直接实例化!')
11 | }
12 | }
13 |
14 | /* 烧开水,共用方法 */
15 | Beverage.prototype.boilWater = function() {
16 | console.log('水已经煮沸')
17 | }
18 |
19 | /* 冲泡饮料,抽象方法 */
20 | Beverage.prototype.brewDrink = function() {
21 | throw new Error('抽象方法不能调用!')
22 | }
23 |
24 | /* 倒杯子里,共用方法 */
25 | Beverage.prototype.pourCup = function() {
26 | console.log('倒进杯子里')
27 | }
28 |
29 | /* 加调味品,抽象方法 */
30 | Beverage.prototype.addCondiment = function() {
31 | throw new Error('抽象方法不能调用!')
32 | }
33 |
34 | /* 制作流程,模板方法 */
35 | Beverage.prototype.init = function() {
36 | this.boilWater()
37 | this.brewDrink()
38 | this.pourCup()
39 | this.addCondiment()
40 | }
41 |
42 | /* 咖啡类,子类 */
43 | var Coffee = function() {}
44 | Coffee.prototype = new Beverage()
45 |
46 | /* 冲泡饮料,覆盖抽象方法 */
47 | Coffee.prototype.brewDrink = function() {
48 | console.log('冲泡咖啡')
49 | }
50 |
51 | /* 加调味品,覆盖抽象方法 */
52 | Coffee.prototype.addCondiment = function() {
53 | console.log('加点咖啡伴侣')
54 | }
55 |
56 | var coffee = new Coffee()
57 | coffee.init()
58 |
59 | // 输出:水已经煮沸
60 | // 输出:冲泡咖啡
61 | // 输出:倒进杯子里
62 | // 输出:加点咖啡伴侣
63 |
--------------------------------------------------------------------------------
/21-模板方法模式/21-02.coffee demo2 class.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 模板方法模式
3 | * 作者: SHERlocked93
4 | * 功能: 咖啡厅例子 使用class方式
5 | */
6 |
7 | /* 饮料类,父类 */
8 | class Beverage {
9 | constructor() {
10 | if (new.target === Beverage) {
11 | throw new Error('抽象类不能直接实例化!')
12 | }
13 | }
14 |
15 | /* 烧开水,共用方法 */
16 | boilWater() {
17 | console.log('水已经煮沸')
18 | }
19 |
20 | /* 冲泡饮料,抽象方法 */
21 | brewDrink() {
22 | throw new Error('抽象方法不能调用!')
23 | }
24 |
25 | /* 倒杯子里,共用方法 */
26 | pourCup() {
27 | console.log('倒进杯子里')
28 | }
29 |
30 | /* 加调味品,抽象方法 */
31 | addCondiment() {
32 | throw new Error('抽象方法不能调用!')
33 | }
34 |
35 | /* 制作流程,模板方法 */
36 | init() {
37 | this.boilWater()
38 | this.brewDrink()
39 | this.pourCup()
40 | this.addCondiment()
41 | }
42 | }
43 |
44 | /* 咖啡类,子类 */
45 | class Coffee extends Beverage {
46 | constructor() { super() }
47 |
48 | /* 冲泡饮料,覆盖抽象方法 */
49 | brewDrink() {
50 | console.log('冲泡咖啡')
51 | }
52 |
53 | /* 加调味品,覆盖抽象方法 */
54 | addCondiment() {
55 | console.log('加点咖啡伴侣')
56 | }
57 | }
58 |
59 | /* 茶类,子类 */
60 | class Tea extends Beverage {
61 | constructor() { super() }
62 |
63 | /* 冲泡饮料,覆盖抽象方法 */
64 | brewDrink() {
65 | console.log('冲泡茶')
66 | }
67 |
68 | /* 注意这里,没有覆盖加调味品抽象方法 */
69 | }
70 |
71 | const coffee = new Coffee()
72 | coffee.init()
73 |
74 | const tea = new Tea()
75 | tea.init()
76 |
77 | // 输出:水已经煮沸
78 | // 输出:冲泡咖啡
79 | // 输出:倒进杯子里
80 | // 输出:加点咖啡伴侣
81 |
82 | // 输出:水已经煮沸
83 | // 输出:冲泡茶
84 | // 输出:倒进杯子里
85 | // Error: 抽象方法不能调用!
86 |
--------------------------------------------------------------------------------
/21-模板方法模式/21-03.coffee demo3 param.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 模板方法模式
3 | * 作者: SHERlocked93
4 | * 功能: 通用实现
5 | */
6 |
7 | /* 虚拟方法 */
8 | const abstractFunc = function() {
9 | throw new Error('抽象方法不能调用!')
10 | }
11 |
12 | /* 空方法 */
13 | const emptyFunc = function() {}
14 |
15 | /* 饮料方法,方法体就是模板方法 */
16 | function beverageFunc({
17 | boilWater = function() { // 烧开水,共用方法
18 | console.log('水已经煮沸')
19 | },
20 | brewDrink = abstractFunc, // 冲泡饮料,抽象方法
21 | pourCup = function() { // 倒杯子里,共用方法
22 | console.log('倒进杯子里')
23 | },
24 | addCondiment = abstractFunc // 加调味品,抽象方法
25 | }) {
26 | boilWater()
27 | brewDrink()
28 | pourCup()
29 | addCondiment()
30 | }
31 |
32 | /* 制作咖啡 */
33 | beverageFunc({
34 | brewDrink: function() { // 冲泡饮料,覆盖抽象方法
35 | console.log('水已经煮沸')
36 | },
37 | addCondiment: function() { // 加调味品,覆盖抽象方法
38 | console.log('加点咖啡伴侣')
39 | }
40 | })
41 |
--------------------------------------------------------------------------------
/21-模板方法模式/21-04.coffee demo4 class param.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 模板方法模式
3 | * 作者: SHERlocked93
4 | * 功能: 通用实现
5 | */
6 |
7 | /* 虚拟方法 */
8 | const abstractFunc = function() {
9 | throw new Error('抽象方法不能调用!')
10 | }
11 |
12 | /* 饮料方法 */
13 | class Beverage {
14 | constructor({
15 | brewDrink = abstractFunc, // 冲泡饮料,抽象方法
16 | addCondiment = abstractFunc // 加调味品,抽象方法
17 | }) {
18 | this.brewDrink = brewDrink
19 | this.addCondiment = addCondiment
20 | }
21 |
22 | /* 烧开水,共用方法 */
23 | boilWater() {
24 | console.log('水已经煮沸')
25 | }
26 |
27 | /* 倒杯子里,共用方法 */
28 | pourCup() {
29 | console.log('倒进杯子里')
30 | }
31 |
32 | /* 模板方法 */
33 | init() {
34 | this.boilWater()
35 | this.brewDrink()
36 | this.pourCup()
37 | this.addCondiment()
38 | }
39 | }
40 |
41 | /* 咖啡 */
42 | const coffee = new Beverage({
43 | /* 冲泡饮料,覆盖抽象方法 */
44 | brewDrink: function() {
45 | console.log('水已经煮沸')
46 | },
47 |
48 | /* 加调味品,覆盖抽象方法 */
49 | addCondiment: function() {
50 | console.log('加点咖啡伴侣')
51 | }
52 | })
53 |
54 | coffee.init()
55 |
56 | // 输出:水已经煮沸
57 | // 输出:冲泡咖啡
58 | // 输出:倒进杯子里
59 | // 输出:加点咖啡伴侣
60 |
--------------------------------------------------------------------------------
/21-模板方法模式/21-05.template class.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 模板方法模式
3 | * 作者: SHERlocked93
4 | * 功能: 通用实现
5 | */
6 |
7 | /* 抽象父类 */
8 | class AbstractClass {
9 | constructor() {
10 | if (new.target === AbstractClass) {
11 | throw new Error('抽象类不能直接实例化!')
12 | }
13 | }
14 |
15 | /* 共用方法 */
16 | operate1() {
17 | console.log('operate1')
18 | }
19 |
20 | /* 抽象方法 */
21 | operate2() {
22 | throw new Error('抽象方法不能调用!')
23 | }
24 |
25 | /* 模板方法 */
26 | templateMethod() {
27 | this.operate1()
28 | this.operate2()
29 | }
30 | }
31 |
32 | /* 实例子类,继承抽象父类 */
33 | class ConcreteClass extends AbstractClass {
34 | constructor() { super() }
35 |
36 | /* 覆盖抽象方法 operate2 */
37 | operate2() {
38 | console.log('operate2')
39 | }
40 | }
41 |
42 | const instance = new ConcreteClass()
43 | instance.templateMethod()
44 |
45 | // 输出:operate1
46 | // 输出:operate2
47 |
--------------------------------------------------------------------------------
/21-模板方法模式/21-06.template class param.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 模板方法模式
3 | * 作者: SHERlocked93
4 | * 功能: 通用实现
5 | */
6 |
7 | /* 虚拟方法 */
8 | const abstractFunc = function() {
9 | throw new Error('抽象方法不能调用!')
10 | }
11 |
12 | /* 饮料方法 */
13 | class AbstractClass {
14 | constructor({
15 | operate2 = abstractFunc // 抽象方法
16 | }) {
17 | this.operate2 = operate2
18 | }
19 |
20 | /* 共用方法 */
21 | operate1() {
22 | console.log('operate1')
23 | }
24 |
25 | /* 模板方法 */
26 | init() {
27 | this.operate1()
28 | this.operate2()
29 | }
30 | }
31 |
32 | /* 咖啡 */
33 | const instance = new AbstractClass({
34 | /* 覆盖抽象方法 */
35 | operate2: function() {
36 | console.log('operate2')
37 | }
38 | })
39 |
40 | instance.init()
41 |
42 | // 输出:operate1
43 | // 输出:operate2
44 |
--------------------------------------------------------------------------------
/21-模板方法模式/21-06.template higher-order function.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 模板方法模式
3 | * 作者: SHERlocked93
4 | * 功能: 通用实现 高阶函数
5 | */
6 |
7 | /* 虚拟方法 */
8 | const abstractFunc = function() {
9 | throw new Error('抽象方法不能调用!')
10 | }
11 |
12 | /* 空方法 */
13 | const emptyFunc = function() {}
14 |
15 | /* 饮料方法 */
16 | class AbstractClass {
17 | constructor({
18 | operate2 = abstractFunc // 抽象方法
19 | }) {
20 | this.operate2 = operate2
21 | }
22 |
23 | /* 共用方法 */
24 | operate1() {
25 | console.log('operate1')
26 | }
27 |
28 | /* 模板方法 */
29 | init() {
30 | this.operate1()
31 | this.operate2()
32 | }
33 | }
34 |
35 | /* 咖啡 */
36 | const instance = new AbstractClass({
37 | /* 覆盖抽象方法 */
38 | operate2: function() {
39 | console.log('operate2')
40 | }
41 | })
42 |
43 | instance.init()
44 |
45 | // 输出:operate1
46 | // 输出:operate2
47 |
--------------------------------------------------------------------------------
/21-模板方法模式/模板方法模式-咖啡厅.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/21-模板方法模式/模板方法模式-咖啡厅.png
--------------------------------------------------------------------------------
/21-模板方法模式/模板方法模式-模板方法模式.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/21-模板方法模式/模板方法模式-模板方法模式.png
--------------------------------------------------------------------------------
/21-模板方法模式/模板方法模式.xml:
--------------------------------------------------------------------------------
1 | 7Vpbl6I4EP41PtqHEPDy2NLt7NntOWfO9pnLPkaImp1I2BBH7V8/CRQicmmc1cGZ1hdJESqhvu+rCoQe9lbbd5JEy/cioLxnW8G2hx96to2G9lD/GcsOLJaDU8tCsiC1Wbnhmb1Q6OiCdc0CGoMtNSkhuGJR0eiLMKS+KtiIlGJT7DYXPCgYIrKghWkYw7NPOC11+8wCtUyt7gjn9j8oWyxhZAfBiRnxvy6kWIcwXChCmp5ZkcwLjBgvSSA2Byb82MOeFEKlR6utR7kJaxaw8K+/nzyvv6UvPn6eWB//jD3ZT51NT7lkf2+Shuq8ru1x6vsb4WuIJNys2mWhNeGJengSKym+Uk9wIfWJJFB4ApdTqei2Cmgy48e4vXIXaB9azVYqVlTJnb4u8z6GCQJR7SEwd5Ojbg+BlMsC4nAhAaYt9r7zoOkDiNsJMcTW6zFMGEaNF0sHbbNkij5HxDdnN1qR2rZUKz3qA9oHOqOxDsZkLkI1JSvGzV1/ojIgIQEzSBENdJuTGeWTPaOPoJozzjNTz8aPg+nU8+pwFXp2TJnhRmbGAYmXyfRRE+avYpvSrQwugNm322LpXApLVIHlgCsTpoiEBVAH/62N9BMU+nECw73ugMbRNglSdl4fLeD/PI48EfqSKupxEseZV327qePiYEfmO0VXESeKvqdqKYKs10z+zzs7orsmhqridAMjwUQ4W4S66WsiUW2fGJoxnefv4cSKBYEZplJERZkVSHuolXGmlQ8iZoqJygGfjjrsB74c/XFL+l+K/fYvVgz6yBlcXTW4FYO2arjyWuD8AqXgfqYBI75KSkFNcm9XGW45/CysrUrhzk9M4W4JRxroByVoCqmJsRAh4Y+59SjieZ8nISKI/L9UqR2EnqyVKBJDR0zuvpjr79ys+Q+4SxoP20JrB61ybktnb6Z8GirQLxZr6dOGflAuFJEL2uivpvBIqvXFvhVnd/4aUq4ZNxQP44NbwohHncJYXguIiEqdoPHhwrsm/560Snh9TWA3QfUjibB5aWZj584trM3cbNF3kBvR2KrIjdal8HBusmqUldtWVsNOZeXWyQq9QVlhF3Utq8FNVo2yGraVFe5UVsM6WdlvUFZOxuruZDWqw8N5g3gMLLdjPAZvdzHXRxa+utXc8FZ1mqrOqGXRQVY19D+n6NTmuN9/KVchqu7XcuObqJpEhayWqhp0upLrGMUChjmktSgSqe7NJyDa4Jv32MzPzFPGc/dB1gleM2sLnM/JcLClYSW/Spoci/5qaNPtg7VT3vz2hU58LVJxebNA0pi9wIafiXEkWKiSGbuTnvvQO2WboGYrS4M8T361kJ5zKxLXbN5m6dy6Q2NnXMjn8Bq3NXrg/IMJVe4ZoSqn2fViPo81p46x30/wx+mAyt+1XN0D4Zm2Ik+u1N0/HjpldECst9R/Tak/+xjyurcqUDn1X93Lhq60fslXD7qZf0CaJu78A138+B0=7VvbcuI4EP0aPUJJlq+PGExmqpLZ7DI1m+zLlMEKODGINUqAfP1KtoyxLRtIAmSTUFRFasm69DndLbUJwN3p6iL255MrGpAIaDBYAdwDmoYszeJ/hGQtJVDHqWQch0Eqg7lgED4T2dGQ0scwIAspS0WM0oiF86JwRGczMmIFmR/HdFnsdkejoCCY+2NSWIYQDEZ+RCrd/g4DNkmlho1z+TcSjidyZh3JhqE/ehjH9HEmp5vRGUlbpn42ipxxMfEDutwSYQ/gbkwpS0vTVZdEQq1FhfVrWjcrjsmM7fPA8/Ty6fnpj9vFavjzQfvdin9e9FpIS4d58qNHqQq5WrbOdCP2NwfYXbCYPpAujWjMG5KdYre6CrmwJxIzslKB5w8jUlYDZxahU8LiNe8nn2oh3UwflKzSLEmzZQ6RZkkGTQrwyF34khbjzeC5gnhB6ugAfdm71ZWwgYhBINfPchIyMpj7I9G65NbDZRM25ZP20EanGeW4Mtw7OmN9fxpGYtO/SBz4M1+Kpdkgk9cjf0gid8O+Eip3YRRlIqBhz+z3u906CClfXcjEdLZYceAvJsnykRLeZhqVQa+CK7FsaftCqb8eSm7o33//sAfz6yUa3hP27eo7bumwiqVnANsGrgk8Hbg94HSB54COAToe8Ezg8K9TwZtvmKlAbYBEivwoHM94dcSVS7jcFeoLuVPqyIZpGARiGiWLijwroLZFFg1mZLmmi5CFVDnhZanDZuJaW96TEvX44wr+CFoK/I8Fv8JyScBjgqzSmE3omM78yMulJZ3nfS4pnUvd8/HZWirff2S0SA2us3h9I55vG1n1Vg6XVHqrQm0ta1U/ka5eLLkWFyla0Md4JHvdxw/GP3dTa+DAKdRH3b8ugrglzY758ZjIR6d/3l9erW+vh4H+8OPfXzzE3wxaNRYdk8hn4VNxHa/Bq2mRZWuFwOEFbrN94LiJkfZApy+aOtx+uYmbkbDOYcxLY7bR20v99W7vrDXBtU+cbIiHELeNQkQ0ssPFthk5UGFG8FhmBCsK/axmhKtmpOynn9OMsMKMTGB3xJcXXAhcHXgWsLOg52rAtT+4GWEDnduMUEWhn9WM9D3NyDinGenqaJSYizAaDDrogxuNjs3TGU39eaQKQgd0YHIkgIDf37nEQQKQ/AD/rmDZcbY+GBYTGmf2ZQpYXpBS2Dt/cIi+MDRK6tJMBYst1FZcRfkF5Vjef7fGPmBWYQfz67lVe6l0qlAaWAEkfIOwoFyeqfRI/IbCPY8oGO8vLLwhCtkoleOV4nSlmSf0SJYCFhvYXZHp+XRoOOdGQ5FDFRcOJ7nAGyLd9hlhQYbiKn9SXJDiUPteArfmlA6fjn3+sI0UOamvuN3ArXprgOVj2cY8zhfM0V7RXLwp6CZJE17wQAf//xxVMzaaXrQ8Q4XMaR2VKp7zq50nMlVpCpiXP0AEOQgYBN8BMurYzm/fzocI6YcBYupnB0TbI0SRWdARP6HIY0BjSCKrkN3IVlFOEoZp/pDX8oyhqBQThlsxCCafIyQOq+Bs6d5QpEEy2d55QznDNQ35Ard/rGAV0Hey8JGNka5fPpbDWhlJ04q/esCWUxwozYxWBkr4sdn3Kyij8K4NlBlF/mIRjo7DGj9mJWomsn4otiQT04GsVd+8b/MsT3UXEt153rsm1f0yfjalK7cT2w3h7VxERlAr0M8wjJfxGGfn7iwxqZUGOjKPs6zDaV+pFDib28Y2bdM3L2WfmxNZHbXe2oU2HHlf8VKlzqVZ56WCwoN9UWEHFewTUQGflgrmFxUOpcLRmNA2LAvZfL2WDu3sHXx+7GkjC0Lbgg5v1OGJXYb1xZNDeVJzbnk1T8w2cizbdEweN2xo6yWeWG249UGnpYn9RZNDaXK0M0ajO7H1tmlbWLN1C/Kbuf5GNOHV/Cf8aff8XySw9x8=
--------------------------------------------------------------------------------
/22-迭代器模式/22-01.iterator demo1.js:
--------------------------------------------------------------------------------
1 | var bills = ['MCK013840031', 'MCK013840032', 'MCK013840033', 'MCK013840034', 'MCK013840035']
2 |
3 | bills.forEach(function(bill) {
4 | console.log('当前钞票的冠字号为 ' + bill)
5 | })
6 |
--------------------------------------------------------------------------------
/22-迭代器模式/22-02.iterator demo2.js:
--------------------------------------------------------------------------------
1 | var forEach = function(arr, cb) {
2 | for (var i = 0; i < arr.length; i++) {
3 | cb.call(arr[i], arr[i], i, arr)
4 | }
5 | }
6 |
7 | forEach(['hello', 'world', '!'], function(currValue, idx, arr) {
8 | console.log('当前值 ' + currValue + ',索引为 ' + idx)
9 | })
10 |
11 | // 输出: 当前值 hello,索引为 0
12 | // 输出: 当前值 world,索引为 1
13 | // 输出: 当前值 !,索引为 2
14 |
--------------------------------------------------------------------------------
/22-迭代器模式/22-03.iterator demo3.js:
--------------------------------------------------------------------------------
1 | var foo = {
2 | a: 1
3 | }
4 |
5 | for (var key of foo) {
6 | console.log(key)
7 | }
8 |
9 | // 输出: Uncaught TypeError: foo is not iterable
10 |
--------------------------------------------------------------------------------
/22-迭代器模式/22-04.iterator demo4.js:
--------------------------------------------------------------------------------
1 | var bar = {
2 | a: 1,
3 | [Symbol.iterator]: function() {
4 | var valArr = [
5 | { value: 'hello', done: false },
6 | { value: 'world', done: false },
7 | { value: '!', done: false },
8 | { value: undefined, done: true }
9 | ]
10 | return {
11 | next: function() {
12 | return valArr.shift()
13 | }
14 | }
15 | }
16 | }
17 |
18 | for (var key of bar) {
19 | console.log(key)
20 | }
21 |
22 | // 输出: hello
23 | // 输出: world
24 | // 输出: !
25 |
--------------------------------------------------------------------------------
/23-命令模式/23-01.command demo1.js:
--------------------------------------------------------------------------------
1 | var canvas = document.getElementById('my-canvas')
2 | var CanvasWidth = 400 // 画布宽度
3 | var CanvasHeight = 400 // 画布高度
4 | var CanvasStep = 40 // 动作步长
5 | canvas.width = CanvasWidth
6 | canvas.height = CanvasHeight
7 |
8 | // 移动对象类
9 | var Role = function(x, y, imgSrc) {
10 | this.x = x
11 | this.y = y
12 | this.canvas = document.getElementById('my-canvas')
13 | this.ctx = this.canvas.getContext('2d')
14 | this.img = new Image()
15 | this.img.style.width = CanvasStep
16 | this.img.style.height = CanvasStep
17 | this.img.src = imgSrc
18 | this.img.onload = () => {
19 | this.ctx.drawImage(this.img, x, y, CanvasStep, CanvasStep)
20 | this.move(0, 0)
21 | }
22 | }
23 |
24 | Role.prototype.move = function(x, y) {
25 | this.ctx.clearRect(this.x, this.y, CanvasStep, CanvasStep)
26 | this.x += x
27 | this.y += y
28 | this.ctx.drawImage(this.img, this.x, this.y, CanvasStep, CanvasStep)
29 | }
30 |
31 | /* ----- 客户端 ----- */
32 | var mario = new Role(200, 200, 'https://i.loli.net/2019/08/09/sqnjmxSZBdPfNtb.jpg')
33 | // var monster = new Role(160, 160, 'https://i.loli.net/2019/08/12/XCTzcdbhriLlskv.png')
34 |
35 | // 设置按钮命令
36 | var elementUp = document.getElementById('up-btn')
37 | elementUp.onclick = function() {
38 | mario.move(0, -CanvasStep)
39 | }
40 |
41 | var elementDown = document.getElementById('down-btn')
42 | elementDown.onclick = function() {
43 | mario.move(0, CanvasStep)
44 | }
45 |
46 | var elementLeft = document.getElementById('left-btn')
47 | elementLeft.onclick = function() {
48 | mario.move(-CanvasStep, 0)
49 | }
50 |
51 | var elementRight = document.getElementById('right-btn')
52 | elementRight.onclick = function() {
53 | mario.move(CanvasStep, 0)
54 | }
55 |
--------------------------------------------------------------------------------
/23-命令模式/23-02.command demo2.js:
--------------------------------------------------------------------------------
1 | const canvas = document.getElementById('my-canvas')
2 | const CanvasWidth = 400 // 画布宽度
3 | const CanvasHeight = 400 // 画布高度
4 | const CanvasStep = 40 // 动作步长
5 | canvas.width = CanvasWidth
6 | canvas.height = CanvasHeight
7 |
8 | const btnUp = document.getElementById('up-btn')
9 | const btnDown = document.getElementById('down-btn')
10 | const btnLeft = document.getElementById('left-btn')
11 | const btnRight = document.getElementById('right-btn')
12 |
13 | // 移动对象类
14 | class Role {
15 | constructor(x, y, imgSrc) {
16 | this.x = x
17 | this.y = y
18 | this.canvas = document.getElementById('my-canvas')
19 | this.ctx = this.canvas.getContext('2d')
20 | this.img = new Image()
21 | this.img.style.width = CanvasStep
22 | this.img.style.height = CanvasStep
23 | this.img.src = imgSrc
24 | this.img.onload = () => {
25 | this.ctx.drawImage(this.img, x, y, CanvasStep, CanvasStep)
26 | this.move(0, 0)
27 | }
28 | }
29 |
30 | move(x, y) {
31 | this.ctx.clearRect(this.x, this.y, CanvasStep, CanvasStep)
32 | this.x += x
33 | this.y += y
34 | this.ctx.drawImage(this.img, this.x, this.y, CanvasStep, CanvasStep)
35 | }
36 | }
37 |
38 | // 向上移动命令对象
39 | class MoveUpCommand {
40 | constructor(receiver) {
41 | this.receiver = receiver
42 | }
43 |
44 | execute(role) {
45 | this.receiver.move(0, -CanvasStep)
46 | }
47 | }
48 |
49 | // 向下移动命令对象
50 | class MoveDownCommand {
51 | constructor(receiver) {
52 | this.receiver = receiver
53 | }
54 |
55 | execute(role) {
56 | this.receiver.move(0, CanvasStep)
57 | }
58 | }
59 |
60 | // 向左移动命令对象
61 | class MoveLeftCommand {
62 | constructor(receiver) {
63 | this.receiver = receiver
64 | }
65 |
66 | execute(role) {
67 | this.receiver.move(-CanvasStep, 0)
68 | }
69 | }
70 |
71 | // 向右移动命令对象
72 | class MoveRightCommand {
73 | constructor(receiver) {
74 | this.receiver = receiver
75 | }
76 |
77 | execute(role) {
78 | this.receiver.move(CanvasStep, 0)
79 | }
80 | }
81 |
82 | // 设置按钮命令
83 | const setCommand = function(element, command) {
84 | element.onclick = function() {
85 | command.execute()
86 | }
87 | }
88 |
89 | /* ----- 客户端 ----- */
90 | const mario = new Role(200, 200, 'https://i.loli.net/2019/08/09/sqnjmxSZBdPfNtb.jpg')
91 | const moveUpCommand = new MoveUpCommand(mario)
92 | const moveDownCommand = new MoveDownCommand(mario)
93 | const moveLeftCommand = new MoveLeftCommand(mario)
94 | const moveRightCommand = new MoveRightCommand(mario)
95 |
96 | setCommand(btnUp, moveUpCommand)
97 | setCommand(btnDown, moveDownCommand)
98 | setCommand(btnLeft, moveLeftCommand)
99 | setCommand(btnRight, moveRightCommand)
100 |
--------------------------------------------------------------------------------
/23-命令模式/23-03.command demo3.js:
--------------------------------------------------------------------------------
1 | const canvas = document.getElementById('my-canvas')
2 | const CanvasWidth = 400 // 画布宽度
3 | const CanvasHeight = 400 // 画布高度
4 | const CanvasStep = 40 // 动作步长
5 | canvas.width = CanvasWidth
6 | canvas.height = CanvasHeight
7 |
8 | const btnUp = document.getElementById('up-btn')
9 | const btnDown = document.getElementById('down-btn')
10 | const btnLeft = document.getElementById('left-btn')
11 | const btnRight = document.getElementById('right-btn')
12 |
13 | // 移动对象类
14 | class Role {
15 | constructor(x, y, imgSrc) {
16 | this.x = x
17 | this.y = y
18 | this.canvas = document.getElementById('my-canvas')
19 | this.ctx = this.canvas.getContext('2d')
20 | this.img = new Image()
21 | this.img.style.width = CanvasStep
22 | this.img.style.height = CanvasStep
23 | this.img.src = imgSrc
24 | this.img.onload = () => {
25 | this.ctx.drawImage(this.img, x, y, CanvasStep, CanvasStep)
26 | this.move(0, 0)
27 | }
28 | }
29 |
30 | move(x, y) {
31 | this.ctx.clearRect(this.x, this.y, CanvasStep, CanvasStep)
32 | this.x += x
33 | this.y += y
34 | this.ctx.drawImage(this.img, this.x, this.y, CanvasStep, CanvasStep)
35 | }
36 | }
37 |
38 | // 向上移动命令对象
39 | const MoveUpCommand = {
40 | execute(role) {
41 | role.move(0, -CanvasStep)
42 | }
43 | }
44 |
45 | // 向下移动命令对象
46 | const MoveDownCommand = {
47 | execute(role) {
48 | role.move(0, CanvasStep)
49 | }
50 | }
51 |
52 | // 向左移动命令对象
53 | const MoveLeftCommand = {
54 | execute(role) {
55 | role.move(-CanvasStep, 0)
56 | }
57 | }
58 |
59 | // 向右移动命令对象
60 | const MoveRightCommand = {
61 | execute(role) {
62 | role.move(CanvasStep, 0)
63 | }
64 | }
65 |
66 | // 设置按钮命令
67 | const setCommand = function(element, role, command) {
68 | element.onclick = function() {
69 | command.execute(role)
70 | }
71 | }
72 |
73 | /* ----- 客户端 ----- */
74 | const mario = new Role(200, 200, 'https://i.loli.net/2019/08/09/sqnjmxSZBdPfNtb.jpg')
75 |
76 | setCommand(btnUp, mario, MoveUpCommand)
77 | setCommand(btnDown, mario, MoveDownCommand)
78 | setCommand(btnLeft, mario, MoveLeftCommand)
79 | setCommand(btnRight, mario, MoveRightCommand)
80 |
--------------------------------------------------------------------------------
/23-命令模式/状态模式-小游戏1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/23-命令模式/状态模式-小游戏1.gif
--------------------------------------------------------------------------------
/23-命令模式/状态模式-小游戏2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/23-命令模式/状态模式-小游戏2.gif
--------------------------------------------------------------------------------
/24-职责链模式/24-01.leader demo1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-08-17
3 | * 作者: SHERlocked93
4 | * 功能: 职责链模式 请假
5 | */
6 |
7 | var askLeave = function(duration) {
8 | if (duration <= 0.5) {
9 | console.log('小组领导经过一番心理斗争:批准了')
10 | } else if (duration <= 1) {
11 | console.log('部门领导经过一番心理斗争:批准了')
12 | } else if (duration <= 2) {
13 | console.log('总经理经过一番心理斗争:批准了')
14 | } else {
15 | console.log('总经理:不准请这么长的假')
16 | }
17 | }
18 |
19 | askLeave(0.5) // 小组领导经过一番心理斗争:批准了
20 | askLeave(1) // 部门领导经过一番心理斗争:批准了
21 | askLeave(2) // 总经理经过一番心理斗争:批准了
22 | askLeave(3) // 总经理:不准请这么长的假
23 |
--------------------------------------------------------------------------------
/24-职责链模式/24-02.leader demo2.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-08-17
3 | * 作者: SHERlocked93
4 | * 功能: 职责链模式 请假
5 | */
6 |
7 | /* 小组领导处理逻辑 */
8 | var askLeaveGroupLeader = function(duration) {
9 | if (duration <= 0.5) {
10 | console.log('小组领导经过一番心理斗争:批准了')
11 | } else
12 | askLeaveDepartmentLeader(duration)
13 | }
14 |
15 | /* 部门领导处理逻辑 */
16 | var askLeaveDepartmentLeader = function(duration) {
17 | if (duration <= 1) {
18 | console.log('部门领导经过一番心理斗争:批准了')
19 | } else
20 | askLeaveGeneralLeader(duration)
21 | }
22 |
23 | /* 总经理处理逻辑 */
24 | var askLeaveGeneralLeader = function(duration) {
25 | if (duration <= 2) {
26 | console.log('总经理经过一番心理斗争:批准了')
27 | } else
28 | console.log('总经理:不准请这么长的假')
29 | }
30 |
31 | askLeaveGroupLeader(0.5) // 小组领导经过一番心理斗争:批准了
32 | askLeaveGroupLeader(1) // 部门领导经过一番心理斗争:批准了
33 | askLeaveGroupLeader(2) // 总经理经过一番心理斗争:批准了
34 | askLeaveGroupLeader(3) // 总经理:不准请这么长的假
35 |
--------------------------------------------------------------------------------
/24-职责链模式/24-03.leader demo3.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-08-17
3 | * 作者: SHERlocked93
4 | * 功能: 职责链模式 请假
5 | */
6 |
7 | /* 小组领导 */
8 | var GroupLeader = {
9 | nextLeader: null,
10 | setNext: function(next) {
11 | this.nextLeader = next
12 | },
13 | handle: function(duration) {
14 | if (duration <= 0.5) {
15 | console.log('小组领导经过一番心理斗争:批准了')
16 | } else
17 | this.nextLeader.handle(duration)
18 | }
19 | }
20 |
21 | /* 部门领导 */
22 | var DepartmentLeader = {
23 | nextLeader: null,
24 | setNext: function(next) {
25 | this.nextLeader = next
26 | },
27 | handle: function(duration) {
28 | if (duration <= 1) {
29 | console.log('部门领导经过一番心理斗争:批准了')
30 | } else
31 | this.nextLeader.handle(duration)
32 | }
33 | }
34 |
35 | /* 总经理 */
36 | var GeneralLeader = {
37 | nextLeader: null,
38 | setNext: function(next) {
39 | this.nextLeader = next
40 | },
41 | handle: function(duration) {
42 | if (duration <= 2) {
43 | console.log('总经理经过一番心理斗争:批准了')
44 | } else
45 | console.log('总经理:不准请这么长的假')
46 | }
47 | }
48 |
49 | GroupLeader.setNext(DepartmentLeader) // 设置小组领导的下一个职责节点为部门领导
50 | DepartmentLeader.setNext(GeneralLeader) // 设置部门领导的下一个职责节点为总经理
51 |
52 | GroupLeader.handle(0.5) // 小组领导经过一番心理斗争:批准了
53 | GroupLeader.handle(1) // 部门领导经过一番心理斗争:批准了
54 | GroupLeader.handle(2) // 总经理经过一番心理斗争:批准了
55 | GroupLeader.handle(3) // 总经理:不准请这么长的假
56 |
--------------------------------------------------------------------------------
/24-职责链模式/24-04.leader demo4.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-08-17
3 | * 作者: SHERlocked93
4 | * 功能: 职责链模式 请假
5 | */
6 |
7 | /* 领导基类 */
8 | var Leader = function() {
9 | this.nextLeader = null
10 | }
11 |
12 | Leader.prototype.setNext = function(next) {
13 | this.nextLeader = next
14 | }
15 |
16 | /* 小组领导 */
17 | var GroupLeader = new Leader()
18 | GroupLeader.handle = function(duration) {
19 | if (duration <= 0.5) {
20 | console.log('小组领导经过一番心理斗争:批准了')
21 | } else
22 | this.nextLeader.handle(duration)
23 | }
24 |
25 | /* 部门领导 */
26 | var DepartmentLeader = new Leader()
27 | DepartmentLeader.handle = function(duration) {
28 | if (duration <= 1) {
29 | console.log('部门领导经过一番心理斗争:批准了')
30 | } else
31 | this.nextLeader.handle(duration)
32 | }
33 |
34 | /* 总经理 */
35 | var GeneralLeader = new Leader()
36 | GeneralLeader.handle = function(duration) {
37 | if (duration <= 2) {
38 | console.log('总经理经过一番心理斗争:批准了')
39 | } else
40 | console.log('总经理:不准请这么长的假')
41 | }
42 |
43 | GroupLeader.setNext(DepartmentLeader) // 设置小组领导的下一个职责节点为部门领导
44 | DepartmentLeader.setNext(GeneralLeader) // 设置部门领导的下一个职责节点为总经理
45 |
46 | GroupLeader.handle(0.5) // 小组领导经过一番心理斗争:批准了
47 | GroupLeader.handle(1) // 部门领导经过一番心理斗争:批准了
48 | GroupLeader.handle(2) // 总经理经过一番心理斗争:批准了
49 | GroupLeader.handle(3) // 总经理:不准请这么长的假
50 |
--------------------------------------------------------------------------------
/24-职责链模式/24-05.leader demo5 es6.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-08-17
3 | * 作者: SHERlocked93
4 | * 功能: 职责链模式 请假
5 | */
6 |
7 | /* 领导基类 */
8 | class Leader {
9 | constructor() {
10 | this.nextLeader = null
11 | }
12 |
13 | setNext(next) {
14 | this.nextLeader = next
15 | }
16 | }
17 |
18 | /* 小组领导 */
19 | class GroupLeader extends Leader {
20 | handle(duration) {
21 | if (duration <= 0.5) {
22 | console.log('小组领导经过一番心理斗争:批准了')
23 | } else
24 | this.nextLeader.handle(duration)
25 | }
26 | }
27 |
28 | /* 部门领导 */
29 | class DepartmentLeader extends Leader {
30 | handle(duration) {
31 | if (duration <= 1) {
32 | console.log('部门领导经过一番心理斗争:批准了')
33 | } else
34 | this.nextLeader.handle(duration)
35 | }
36 | }
37 |
38 | /* 总经理 */
39 | class GeneralLeader extends Leader {
40 | handle(duration) {
41 | if (duration <= 2) {
42 | console.log('总经理经过一番心理斗争:批准了')
43 | } else
44 | console.log('总经理:不准请这么长的假')
45 | }
46 | }
47 |
48 | const zhangSan = new GroupLeader()
49 | const liSi = new DepartmentLeader()
50 | const wangWu = new GeneralLeader()
51 |
52 | zhangSan.setNext(liSi) // 设置小组领导的下一个职责节点为部门领导
53 | liSi.setNext(wangWu) // 设置部门领导的下一个职责节点为总经理
54 |
55 | zhangSan.handle(0.5) // 小组领导经过一番心理斗争:批准了
56 | zhangSan.handle(1) // 部门领导经过一番心理斗争:批准了
57 | zhangSan.handle(2) // 总经理经过一番心理斗争:批准了
58 | zhangSan.handle(3) // 总经理:不准请这么长的假
59 |
--------------------------------------------------------------------------------
/24-职责链模式/24-06.leader demo6.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-08-17
3 | * 作者: SHERlocked93
4 | * 功能: 职责链模式 请假
5 | */
6 |
7 | /* 领导基类 */
8 | var Leader = function() {
9 | this.nextLeader = null
10 | }
11 |
12 | Leader.prototype.setNext = function(next) {
13 | this.nextLeader = next
14 | return next
15 | }
16 |
17 | /* 小组领导 */
18 | var GroupLeader = new Leader()
19 | GroupLeader.handle = function(duration) {
20 | if (duration <= 0.5) {
21 | console.log('小组领导经过一番心理斗争:批准了')
22 | } else
23 | this.nextLeader.handle(duration)
24 | }
25 |
26 | /* 部门领导 */
27 | var DepartmentLeader = new Leader()
28 | DepartmentLeader.handle = function(duration) {
29 | if (duration <= 1) {
30 | console.log('部门领导经过一番心理斗争:批准了')
31 | } else
32 | this.nextLeader.handle(duration)
33 | }
34 |
35 | /* 总经理 */
36 | var GeneralLeader = new Leader()
37 | GeneralLeader.handle = function(duration) {
38 | if (duration <= 2) {
39 | console.log('总经理经过一番心理斗争:批准了')
40 | } else
41 | console.log('总经理:不准请这么长的假')
42 | }
43 |
44 | /* 组装职责链 */
45 | GroupLeader
46 | .setNext(DepartmentLeader) // 设置小组领导的下一个职责节点为部门领导
47 | .setNext(GeneralLeader) // 设置部门领导的下一个职责节点为总经理
48 |
49 | GroupLeader.handle(0.5) // 小组领导经过一番心理斗争:批准了
50 | GroupLeader.handle(1) // 部门领导经过一番心理斗争:批准了
51 | GroupLeader.handle(2) // 总经理经过一番心理斗争:批准了
52 | GroupLeader.handle(3) // 总经理:不准请这么长的假
53 |
--------------------------------------------------------------------------------
/24-职责链模式/24-07.leader demo7 es6.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 创建于 2019-08-17
3 | * 作者: SHERlocked93
4 | * 功能: 职责链模式 请假
5 | */
6 |
7 | /* 领导基类 */
8 | class Leader {
9 | constructor() {
10 | this.nextLeader = null
11 | }
12 |
13 | setNext(next) {
14 | this.nextLeader = next
15 | return next
16 | }
17 | }
18 |
19 | /* 小组领导 */
20 | class GroupLeader extends Leader {
21 | handle(duration) {
22 | if (duration <= 0.5) {
23 | console.log('小组领导经过一番心理斗争:批准了')
24 | } else
25 | this.nextLeader.handle(duration)
26 | }
27 | }
28 |
29 | /* 部门领导 */
30 | class DepartmentLeader extends Leader {
31 | handle(duration) {
32 | if (duration <= 1) {
33 | console.log('部门领导经过一番心理斗争:批准了')
34 | } else
35 | this.nextLeader.handle(duration)
36 | }
37 | }
38 |
39 | /* 总经理 */
40 | class GeneralLeader extends Leader {
41 | handle(duration) {
42 | if (duration <= 2) {
43 | console.log('总经理经过一番心理斗争:批准了')
44 | } else
45 | console.log('总经理:不准请这么长的假')
46 | }
47 | }
48 |
49 | const zhangSan = new GroupLeader()
50 | const liSi = new DepartmentLeader()
51 | const wangWu = new GeneralLeader()
52 |
53 | /* 组装职责链 */
54 | zhangSan
55 | .setNext(liSi) // 设置小组领导的下一个职责节点为部门领导
56 | .setNext(wangWu) // 设置部门领导的下一个职责节点为总经理
57 |
58 | zhangSan.handle(0.5) // 小组领导经过一番心理斗争:批准了
59 | zhangSan.handle(1) // 部门领导经过一番心理斗争:批准了
60 | zhangSan.handle(2) // 总经理经过一番心理斗争:批准了
61 | zhangSan.handle(3) // 总经理:不准请这么长的假
62 |
--------------------------------------------------------------------------------
/24-职责链模式/事件冒泡.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/24-职责链模式/事件冒泡.png
--------------------------------------------------------------------------------
/24-职责链模式/事件冒泡.xml:
--------------------------------------------------------------------------------
1 | 7VnbbqMwEP2aPLbC5pY8pknalfailaK9Pa0ccAldwNSYXPbr1w7mYgNtWgWlVfalxcfDeJhzGA/OyJzFuzuK0vVn4uNoBA1/NzLnIwjHrsP/CmAvAXNSAAEN/QIyamAZ/sUFCEo0D32cSayAGCERC1MV9EiSYI8pGKKUbFWzexL5CpCiACthCGDpoQi3zH6EPlvLp4BujX/AYbCWK9tjs5iIUWkr/WZr5JNtAzIXI3NGCWHFVbyb4UikTk3Lbc9sFRfFCTvmhjvj+++HL9njx6mx+OZObj95SXQlvWxQlMvnHUEn4v5u7gl3y6Nme5kJ5zEn5cRVduBpyg2Am+7qSX4VyP8HL6sSmBMvj0WkcoLHudKNOVasWsJQCQBSkic+Fo8D+PR2HTK8TJEnZrdcexxbsziS0xmj5E9FGaz8bTBleNebQ1AxwwWNSYwZ3XMTeYMryZVankhqt7UwgCOxdUMUJpR6lFoMKsc1X/xCUvYC+mAvfVmKkhPSt4jwE+yhWCQ/WWXpYWwcaKhNi1jeLKnANBRWge2emVbzbdK6IryIvx9aJyqtEFpnptV6m7T64eb9sAotV2V1As7MqtPBqpY2L6ebKms48aeiL+FDL0JZFnpPpc2s0ob9slE5PmmNpNgdOSkxiiPEwo3qvitRcoWvJDw0B5ITC9gKJ6Zhqy4yklMPy7uaLYrmyHS0V9aaqI4YogFmLUc8n2jfMEuFQfZEwFb3OrUMCo+1KKqcvl4n7vM6aUgjIQl+7nXi7NP9Tz4wysEvMbi2y+F815yc76uRfxuK4IsR19VSxkAoW5OAJCha1OjNQx6nsjEXN9RFwHiBOHnbfiDvuW7mXCIGhipiALWCcayIgVahLMsZRMR9AffGpdvLZnZQ0U8uvjiatqO1IVpNO7o4GqCTv1Pryhx3rzOoTsqv/UsWigHVvDuvLEB6iwSMYQqQCbvXGVYoXScWF7SNnm17dLTdY/zKMtb6LCt7sVNvjz0B98al2ZdxDavmrgOc/2oeXM0QioQodNtakTy+2trX+uePO4ii+4Puja11RxnbsKpun1/d5KsVl42ubYZ3rEvQMxIRWgv+ngtTg1AUBonY/LmgMMdvxKlC6KFoKifi0PcPQu06pVDVKg5ZpJSBc5pjinYTJctlQ99Wh76hVgxPdkoB2odPl8aJZakNVvXKn40T++I5afWQ5Y54ek74sP6xrSh19Q+W5uIf
--------------------------------------------------------------------------------
/25-中介者模式/25-01.dating demo1 class.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 中介者模式
3 | * 作者: SHERlocked93
4 | * 功能: 相亲例子 class方式
5 | */
6 |
7 |
8 | class Person {
9 | /**
10 | * 个人信息
11 | * @param name 名字
12 | * @param info 个人信息
13 | * @param target 要求
14 | */
15 | constructor(name, info, target) {
16 | this.name = name
17 | this.info = info
18 | this.target = target
19 | this.enemyList = [] // 考虑列表
20 | }
21 |
22 | /**
23 | * 注册对方
24 | * @param enemy
25 | */
26 | registEnemy(...enemy) {
27 | this.enemyList.push(...enemy)
28 | }
29 |
30 | /**
31 | * 检查所有考虑对象是否满足要求
32 | */
33 | checkAllPurpose() {
34 | this.enemyList.forEach(enemy => enemy.info && this.checkPurpose(enemy))
35 | }
36 |
37 | /**
38 | * 检查对方是否满足自己的要求,并发信息
39 | * @param enemy
40 | */
41 | checkPurpose(enemy) {
42 | const result = Object.keys(this.target) // 是否满足自己的要求
43 | .every(key => {
44 | const [low, high] = this.target[key]
45 | return low <= enemy.info[key] && enemy.info[key] <= high
46 | })
47 | enemy.receiveResult(result, this, enemy) // 通知对方
48 | }
49 |
50 | /**
51 | * 接受到对方的信息
52 | * @param result
53 | * @param me
54 | * @param they
55 | */
56 | receiveResult(result, they, me) {
57 | result
58 | ? console.log(`${ they.name }:我觉得合适~ \t(我的要求 ${ me.name } 已经满足)`)
59 | : console.log(`${ they.name }:你是个好人! \t(我的要求 ${ me.name } 不能满足!)`)
60 | }
61 | }
62 |
63 | /* 男方 */
64 | const ZhangXiaoShuai = new Person('张小帅',
65 | { age: 25, height: 171, salary: 5000 },
66 | { age: [23, 27] })
67 |
68 | /* 男方家长 */
69 | const ZhangXiaoShuaiParent = new Person('张小帅家长', null,
70 | { height: [160, 167] })
71 |
72 | /* 女方 */
73 | const LiXiaoMei = new Person('李小美',
74 | { age: 23, height: 160 },
75 | { age: [25, 27] })
76 |
77 | /* 女方家长 */
78 | const LiXiaoMeiParent = new Person('李小美家长', null,
79 | { salary: [10000, 20000] })
80 |
81 | /* 注册 */
82 | ZhangXiaoShuai.registEnemy(LiXiaoMei, LiXiaoMeiParent)
83 | LiXiaoMei.registEnemy(ZhangXiaoShuai, ZhangXiaoShuaiParent)
84 | ZhangXiaoShuaiParent.registEnemy(LiXiaoMei, LiXiaoMeiParent)
85 | LiXiaoMeiParent.registEnemy(ZhangXiaoShuai, ZhangXiaoShuaiParent)
86 |
87 | /* 检查对方是否符合要求 */
88 | ZhangXiaoShuai.checkAllPurpose()
89 | LiXiaoMei.checkAllPurpose()
90 | ZhangXiaoShuaiParent.checkAllPurpose()
91 | LiXiaoMeiParent.checkAllPurpose()
92 |
93 | // 张小帅:我觉得合适~ (我的要求 李小美 已经满足)
94 | // 李小美:我觉得合适~ (我的要求 张小帅 已经满足)
95 | // 张小帅家长:我觉得合适~ (我的要求 李小美 已经满足)
96 | // 李小美家长:你是个好人! (我的要求 张小帅 不能满足!)
97 |
--------------------------------------------------------------------------------
/25-中介者模式/25-02.dating demo2.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 中介者模式
3 | * 作者: SHERlocked93
4 | * 功能: 相亲例子
5 | */
6 |
7 | const PersonFunc = {
8 | /**
9 | * 注册对方
10 | * @param enemy
11 | */
12 | registEnemy(...enemy) {
13 | this.enemyList.push(...enemy)
14 | },
15 |
16 | /**
17 | * 检查所有考虑对象是否满足要求
18 | */
19 | checkAllPurpose() {
20 | this.enemyList.forEach(enemy => enemy.info && this.checkPurpose(enemy))
21 | },
22 |
23 | /**
24 | * 检查对方是否满足自己的要求,并发信息
25 | * @param enemy
26 | */
27 | checkPurpose(enemy) {
28 | const result = Object.keys(this.target) // 是否满足自己的要求
29 | .every(key => {
30 | const [low, high] = this.target[key]
31 | return low <= enemy.info[key] && enemy.info[key] <= high
32 | })
33 | enemy.receiveResult(result, this, enemy) // 通知对方
34 | },
35 |
36 | /**
37 | * 接受到对方的信息
38 | * @param result
39 | * @param me
40 | * @param they
41 | */
42 | receiveResult(result, they, me) {
43 | result
44 | ? console.log(`${ they.name }:我觉得合适~ \t(我的要求 ${ me.name } 已经满足)`)
45 | : console.log(`${ they.name }:你是个好人! \t(我的要求 ${ me.name } 不能满足!)`)
46 | }
47 | }
48 |
49 | /* 男方 */
50 | const ZhangXiaoShuai = {
51 | ...PersonFunc,
52 | name: '张小帅',
53 | info: { age: 25, height: 171, salary: 5000 },
54 | target: { age: [23, 27] },
55 | enemyList: []
56 | }
57 |
58 | /* 男方家长 */
59 | const ZhangXiaoShuaiParent = {
60 | ...PersonFunc,
61 | name: '张小帅家长',
62 | info: null,
63 | target: { height: [160, 167] },
64 | enemyList: []
65 | }
66 |
67 | /* 女方 */
68 | const LiXiaoMei = {
69 | ...PersonFunc,
70 | name: '李小美',
71 | info: { age: 23, height: 160 },
72 | target: { age: [25, 27] },
73 | enemyList: []
74 | }
75 |
76 | /* 女方家长 */
77 | const LiXiaoMeiParent = {
78 | ...PersonFunc,
79 | name: '李小美家长',
80 | info: null,
81 | target: { salary: [10000, 20000] },
82 | enemyList: []
83 | }
84 |
85 | /* 注册 */
86 | ZhangXiaoShuai.registEnemy(LiXiaoMei, LiXiaoMeiParent)
87 | LiXiaoMei.registEnemy(ZhangXiaoShuai, ZhangXiaoShuaiParent)
88 | ZhangXiaoShuaiParent.registEnemy(LiXiaoMei, LiXiaoMeiParent)
89 | LiXiaoMeiParent.registEnemy(ZhangXiaoShuai, ZhangXiaoShuaiParent)
90 |
91 | /* 检查对方是否符合要求 */
92 | ZhangXiaoShuai.checkAllPurpose()
93 | LiXiaoMei.checkAllPurpose()
94 | ZhangXiaoShuaiParent.checkAllPurpose()
95 | LiXiaoMeiParent.checkAllPurpose()
96 |
97 | // 张小帅:我觉得合适~ (我的要求 李小美 已经满足)
98 | // 李小美:我觉得合适~ (我的要求 张小帅 已经满足)
99 | // 张小帅家长:我觉得合适~ (我的要求 李小美 已经满足)
100 | // 李小美家长:你是个好人! (我的要求 张小帅 不能满足!)
101 |
--------------------------------------------------------------------------------
/25-中介者模式/25-03.dating demo3.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 模块: 中介者模式
3 | * 作者: SHERlocked93
4 | * 功能: 相亲例子 引入媒人
5 | */
6 |
7 | /* 男方 */
8 | const ZhangXiaoShuai = {
9 | name: '张小帅',
10 | familyType: '男方',
11 | info: { age: 25, height: 171, salary: 5000 },
12 | target: { age: [23, 27] }
13 | }
14 |
15 | /* 男方家长 */
16 | const ZhangXiaoShuaiParent = {
17 | name: '张小帅家长',
18 | familyType: '男方',
19 | info: null,
20 | target: { height: [160, 167] }
21 | }
22 |
23 | /* 女方 */
24 | const LiXiaoMei = {
25 | name: '李小美',
26 | familyType: '女方',
27 | info: { age: 23, height: 160 },
28 | target: { age: [25, 27] }
29 | }
30 |
31 | /* 女方家长 */
32 | const LiXiaoMeiParent = {
33 | name: '李小美家长',
34 | familyType: '女方',
35 | info: null,
36 | target: { salary: [10000, 20000] }
37 | }
38 |
39 | /* 媒人 */
40 | const MatchMaker = {
41 | matchBook: {},
42 |
43 | /**
44 | * 注册各方
45 | * @param personList
46 | */
47 | registPersons(...personList) {
48 | personList.forEach(person => {
49 | if (this.matchBook[person.familyType]) {
50 | this.matchBook[person.familyType].push(person)
51 | } else this.matchBook[person.familyType] = [person]
52 | })
53 | },
54 |
55 | /**
56 | * 检查对方家庭的孩子对象是否满足要求
57 | */
58 | checkAllPurpose() {
59 | Object.keys(this.matchBook)
60 | .forEach((familyType, idx, matchList) =>
61 | matchList
62 | .filter(match => match !== familyType) // 过滤出familyType的成员,比如「赵小美家」
63 | .forEach(enemyFamily => this.matchBook[enemyFamily] // 对「赵小美家」的成员们检查是否符合自己要求
64 | .forEach(enemy => this.matchBook[familyType]
65 | .forEach(person =>
66 | enemy.info && this.checkPurpose(person, enemy) // 逐一检查对方成员是否满足自己要求
67 | )
68 | ))
69 | )
70 | },
71 |
72 | /**
73 | * 检查对方是否满足自己的要求,并发信息
74 | * @param enemy
75 | * @param person
76 | */
77 | checkPurpose(person, enemy) {
78 | const result = Object.keys(person.target) // 是否满足自己的要求
79 | .every(key => {
80 | const [low, high] = person.target[key]
81 | return low <= enemy.info[key] && enemy.info[key] <= high
82 | })
83 | this.receiveResult(result, person, enemy) // 通知对方
84 | },
85 |
86 | /**
87 | * 通知对方信息
88 | * @param result
89 | * @param person
90 | * @param enemy
91 | */
92 | receiveResult(result, person, enemy) {
93 | result
94 | ? console.log(`${ person.name } 觉得合适~ \t(${ enemy.name } 已经满足要求)`)
95 | : console.log(`${ person.name } 觉得不合适! \t(${ enemy.name } 不能满足要求!)`)
96 | }
97 | }
98 |
99 |
100 | /* 注册 */
101 | MatchMaker.registPersons(ZhangXiaoShuai, ZhangXiaoShuaiParent, LiXiaoMei, LiXiaoMeiParent)
102 |
103 | MatchMaker.checkAllPurpose()
104 |
105 | // 输出: 小帅 觉得合适~ (李小美 已经满足要求)
106 | // 输出: 张小帅家长 觉得合适~ (李小美 已经满足要求)
107 | // 输出: 李小美 觉得合适~ (张小帅 已经满足要求)
108 | // 输出: 李小美家长 觉得不合适! (张小帅 不能满足要求!)
109 |
--------------------------------------------------------------------------------
/25-中介者模式/中介者模式.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/25-中介者模式/中介者模式.png
--------------------------------------------------------------------------------
/25-中介者模式/中介者模式.xml:
--------------------------------------------------------------------------------
1 | 5Vtdk6I4FP01PLZFSELCo6i9W7s7VbPVU7U7j7REZQaNhbHV+fUbICCBtqVXO8BMvzS5kBDuPfcjJ9GCk/XxtyTYrj7xkMWWY4dHC04txwEOceS/VHJSEoSUZJlEYS6zz4Kn6AdTD2Il3Uch2ylZLhKcxyLa6sI532zYXGiyIEn4QX9sweNQE2yDJdOmkQqe5kHMGo/9E4VilUsxhWf57yxartSbEVA3noP592XC9xv1ug3fsPzOOihGUWPvVkHID5VJwJkFJwnnIr9aHycsTtWqK+zxwt1yxgnbiDYd/vz2x5f9jI65Szh82BLv9PeXB5qP8hLEe6UJNVlxKlQj571NLxcxO45TVVvQZ5tQXU7ncbDbRXMpXIl1LAVAXu5Ewr+XmnTyHsrq3siGuaC878r2QTUAkY1FFMcTHvMkmwIMMaMhKsct7mTKhn4+YxYu67Y8awaU+pYQZnzNRHKSjxwqpla4WFWsXMgSFgcietGHDxTiluVw5Rs+80i+2LGVe0CqxlHOgWBtiB3fJ3OmelUtWB+IeCOsDYULexVDiSBZMtEYSl5UPvwsyiDyDrh4TbjMkOVPLf/RmhHLQ9aYZhJqjafZhW9R35pRS+qAYmvmpg+MgTXDlj+x6GMDbYIdhY6lhO2iH8Fz9oAt29v047LPxb6Fp1ISxNFyk0JR2ptJYPgvLBGRdO6xurGOwjDt78fBM4v90mcrEFtkfyn0+EYopAKvRFc6IjtqAFChSM2sGlnOuLvsc00wqtFt6R421Kzs3gWGHq6B5wHUwMMXix37ENwQ0jB06q9PqqkcObMJC5WdeSJWfMk3QfwX51sFhm9MiJMyT7AXXIcKO0bi37T7iHiOan/N2jYmqj09qvGzxkk1dtJxRDOkZeLHKC5fUEYx99UoVwGPg9Q7PrMkkvpLgZm9qm24ktrK4sJbar0ApRuRgrEzIpggBwJIiOciDTaAuiMqIw/2sI1cRMxGINLMWLMmtuJYFg4ppA6rSLCnbZCp8SCLFx0wwW6bVxOL6JgCr2HAi97fIruoDg6imv4gUPqsZB/6SvYpZK/ZTdPqu1XomXHGd/pKSxe8o/tQBd0csm89CG/0s5vsVQDBWPB0qacFTw/BN4OnVHxyyrs60CsEReB1C8G5c9bSeteD5DDjcXtA3Rq4bwMUMAwoklX4FUC5tCWgdDDhK1D62VHjdooap5F5x8PKvA9Fid5V5i3ohIoK/X6rEGGnZypEhmOXQ7TQZbfNhaAausCVwHWPiNRB/eQOo37ChiED9bWnR8H/gIx9BTIDzXWtIdNtheQ2AvWk34EaY1SjdwAiHYdqQ6TP6+7TVbF4T2ehLZ3lZh7oNjs3KZlpv52lXtV0TslQQ5RMkaKq+ant0p7kFOrZwRQt0JOl/R39jrT1Ow916XeeIV6owu64qAaBfCHfEwhUCAcXViE+sgl+G+YmeHoThfKFjUMb6PHOqQWyCzuQd9s2NEQ4nZHqEncgSMVURyoaBlCdDwGqQ/StcqdY7psCqmM2D49cD+vmx+7b9n+VGb1GLwxzreghU2C8LQ1Dw8HtZ1vmtLdzp/x3Mc3KMqd5fKVXyxyAQN84AQCaWhzY/r1ng5GHEaYeRZDgrvWJG/oc2K4Mdkmf9Nlk/ga2RdMzfZKGPgfHpBKIeqTR4jigucVUcy3VE+KnckCzTSVytcAAlYPZ91zWlIfkyhTi6kN88LIGgMFTtD3Lus2D0IOrBXsW1YxTRATRXyWs5UXi/WlF164hipoNa44huqbKgP8ymLl1sX0hFRYFdmeYMUTXKIqvuK6QNQM49vhONF2leECx4dACd+RG3N2Yh8ycL/u5TOZ1azLT57scqJP2HmlL2o8IxLpv27An+1KgOPP/gYz+ezDV6dZ6OdFKgf+JhVEgePIxdT6g96nzYY1dM1Tly+b5l8x5rj7/UhzO/gM=
--------------------------------------------------------------------------------
/26-MVC、MVP、MVVM/MVC.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/26-MVC、MVP、MVVM/MVC.png
--------------------------------------------------------------------------------
/26-MVC、MVP、MVVM/MVC1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/26-MVC、MVP、MVVM/MVC1.png
--------------------------------------------------------------------------------
/26-MVC、MVP、MVVM/MVC2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/26-MVC、MVP、MVVM/MVC2.png
--------------------------------------------------------------------------------
/26-MVC、MVP、MVVM/MVP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/26-MVC、MVP、MVVM/MVP.png
--------------------------------------------------------------------------------
/26-MVC、MVP、MVVM/MVP1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/26-MVC、MVP、MVVM/MVP1.png
--------------------------------------------------------------------------------
/26-MVC、MVP、MVVM/MVVM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SHERlocked93/imooc-frontend-design-pattern/de2a47a51bef0e52f7587f3642738178e4813813/26-MVC、MVP、MVVM/MVVM.png
--------------------------------------------------------------------------------
/27-模块模式/27-01.namespace demo1.js:
--------------------------------------------------------------------------------
1 | var MYNS = {}
2 |
3 | MYNS.param1 = 'hello'
4 | MYNS.param2 = 'world'
5 | MYNS.param3 = { prop: 'name' }
6 |
7 | MYNS.method1 = function() {}
8 |
--------------------------------------------------------------------------------
/27-模块模式/27-02.module demo1.js:
--------------------------------------------------------------------------------
1 | var myModule = (function() {
2 | var privateProp = '' // 私有变量
3 | var privateMethod = function() { // 私有方法
4 | console.log(privateProp)
5 | }
6 |
7 | return {
8 | publicProp: 'foo', // 公有变量
9 | publicMethod: function(prop) { // 共有方法
10 | privateProp = prop
11 | privateMethod()
12 | }
13 | }
14 | })()
15 |
16 |
17 | myModule.publicMethod('new prop') // 输出:new prop
18 | myModule.privateProp // Uncaught TypeError: myModule.privateMethod is not a function
19 | myModule.privateProp // undefined
20 |
--------------------------------------------------------------------------------
/27-模块模式/27-03.module demo2.js:
--------------------------------------------------------------------------------
1 | var myModule = (function() {
2 | var privateProp = ''
3 | var printProp = function() {
4 | console.log(privateProp)
5 | }
6 |
7 | function setProp(prop) {
8 | privateProp = prop
9 | printProp()
10 | }
11 |
12 | return {
13 | print: printProp,
14 | set: setProp
15 | }
16 | })()
17 |
18 |
19 | myModule.set('new prop') // 输出:new prop
20 | myModule.setProp() // Uncaught TypeError: myModule.setProp is not a function
21 | myModule.privateProp // undefined
22 |
23 |
--------------------------------------------------------------------------------
/27-模块模式/27-04.module es6 export demo1.js:
--------------------------------------------------------------------------------
1 | export var a = 'a' // 写法一
2 |
3 | var b = 'b' // 写法二
4 | export { b }
5 |
6 | var c = 'c' // 写法三
7 | export { c as e }
8 |
--------------------------------------------------------------------------------
/27-模块模式/27-05.module es6 import demo1.js:
--------------------------------------------------------------------------------
1 | import { a, b as f, e } from './1.js'
2 |
--------------------------------------------------------------------------------
/27-模块模式/27-06.module es6 export default demo2.js:
--------------------------------------------------------------------------------
1 | // 3.js
2 | export default function() { // 写法一
3 | console.log('foo')
4 | }
5 |
6 | function foo() { // 写法二
7 | console.log('foo')
8 | }
9 |
10 | export default foo
11 |
12 | function foo(x, y) { // 写法三
13 | console.log('foo')
14 | }
15 |
16 | export { add as default }
17 |
18 | export default 42 // 写法四
19 |
--------------------------------------------------------------------------------
/27-模块模式/27-07.module es6 import default demo2.js:
--------------------------------------------------------------------------------
1 | // 4.js
2 | import bar from './3.js' // 写法一
3 | bar()
4 | // 输出:foo
5 |
6 | import { default as bar } from './3.js' // 写法二
7 | bar()
8 | // 输出:foo
9 |
--------------------------------------------------------------------------------
/28-链模式/28-01.chain demo1.js:
--------------------------------------------------------------------------------
1 | /* 四边形 */
2 | var rectangle = {
3 | length: null, // 长
4 | width: null, // 宽
5 | color: null, // 颜色
6 |
7 | getSize: function() {
8 | console.log(`length: ${ this.length }, width: ${ this.width }, color: ${ this.color }`)
9 | },
10 |
11 | /* 设置长度 */
12 | setLength: function(length) {
13 | this.length = length
14 | return this
15 | },
16 |
17 | /* 设置宽度 */
18 | setWidth: function(width) {
19 | this.width = width
20 | return this
21 | },
22 |
23 | /* 设置颜色 */
24 | setColor: function(color) {
25 | this.color = color
26 | return this
27 | }
28 | }
29 |
30 | var rect = rectangle
31 | .setLength('100px')
32 | .setWidth('80px')
33 | .setColor('blue')
34 | .getSize()
35 |
36 | // 输出:length: 100px, width: 80px, color: blue
37 |
--------------------------------------------------------------------------------
/28-链模式/28-02.chain demo2.js:
--------------------------------------------------------------------------------
1 | /* 四边形 */
2 | function Rectangle() {
3 | this.length = null // 长
4 | this.width = null // 宽
5 | this.color = null // 颜色
6 | }
7 |
8 | /* 设置长度 */
9 | Rectangle.prototype.setLength = function(length) {
10 | this.length = length
11 | return this
12 | }
13 |
14 | /* 设置宽度 */
15 | Rectangle.prototype.setWidth = function(width) {
16 | this.width = width
17 | return this
18 | }
19 |
20 | /* 设置颜色 */
21 | Rectangle.prototype.setColor = function(color) {
22 | this.color = color
23 | return this
24 | }
25 |
26 | const rect = new Rectangle()
27 | .setLength('100px')
28 | .setWidth('80px')
29 | .setColor('blue')
30 |
31 | console.log(rect)
32 |
33 | // 输出:{length: "100px", width: "80px", color: "blue"}
34 |
--------------------------------------------------------------------------------
/28-链模式/28-03.chain demo3.js:
--------------------------------------------------------------------------------
1 | /* 四边形 */
2 | class Rectangle {
3 | constructor() {
4 | this.length = null // 长
5 | this.width = null // 宽
6 | this.color = null // 颜色
7 | }
8 |
9 | /* 设置长度 */
10 | setLength(length) {
11 | this.length = length
12 | return this
13 | }
14 |
15 | /* 设置宽度 */
16 | setWidth(width) {
17 | this.width = width
18 | return this
19 | }
20 |
21 | /* 设置颜色 */
22 | setColor(color) {
23 | this.color = color
24 | return this
25 | }
26 | }
27 |
28 | const rect = new Rectangle()
29 | .setLength('100px')
30 | .setWidth('80px')
31 | .setColor('blue')
32 |
33 | console.log(rect)
34 |
35 | // 输出:{length: "100px", width: "80px", color: "blue"}
36 |
--------------------------------------------------------------------------------
/28-链模式/28-04.dom demo1.js:
--------------------------------------------------------------------------------
1 | const ul = document.createElement('ul')
2 | ul.setAttribute('id', 'data-list')
3 |
4 | const li1 = document.createElement('li')
5 | const li2 = document.createElement('li')
6 | const li3 = document.createElement('li')
7 |
8 | li1.setAttribute('id', 'data-item')
9 | li2.setAttribute('id', 'data-item')
10 | li3.setAttribute('id', 'data-item')
11 |
12 | const text1 = document.createTextNode('li-item 1')
13 | const text2 = document.createTextNode('li-item 2')
14 | const text3 = document.createTextNode('li-item 3')
15 |
16 | li1.appendChild(text1)
17 | li2.appendChild(text2)
18 | li3.appendChild(text3)
19 |
20 | ul.appendChild(li1)
21 | ul.appendChild(li2)
22 | ul.appendChild(li3)
23 |
--------------------------------------------------------------------------------
/28-链模式/28-05.dom demo2.js:
--------------------------------------------------------------------------------
1 | const createElement = function(tag) {
2 | return tag === 'text'
3 | ? document.createTextNode(tag)
4 | : document.createElement(tag)
5 | }
6 |
7 | HTMLElement.prototype._setAttribute = function(key, value) {
8 | this.setAttribute(key, value)
9 | return this
10 | }
11 |
12 | HTMLElement.prototype._appendChild = function(child) {
13 | this.appendChild(child)
14 | return this
15 | }
16 |
17 | createElement('ul')
18 | ._setAttribute('id', 'data-list')
19 | ._appendChild(
20 | createElement('li')
21 | ._setAttribute('class', 'data-item')
22 | ._appendChild('text', 'li-item 1'))
23 | ._appendChild(
24 | createElement('li')
25 | ._setAttribute('class', 'data-item')
26 | ._appendChild('text', 'li-item 2'))
27 | ._appendChild(
28 | createElement('li')
29 | ._setAttribute('class', 'data-item')
30 | ._appendChild('text', 'li-item 3'))
31 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 设计模式
2 |
3 | 本仓库是慕课专栏的代码仓库
4 |
--------------------------------------------------------------------------------