├── .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 | 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 -------------------------------------------------------------------------------- /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 | 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 | // 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 | 13 | 14 | 29 | 30 | 33 | -------------------------------------------------------------------------------- /19-策略模式/19-07.ElFormDemo.vue: -------------------------------------------------------------------------------- 1 | 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 | 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 -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------