单例模式
一个类只有一个实例,并提供一个访问它的全局访问点。
1 class LoginForm { 2 constructor() { 3 this.state = 'hide' 4 } 5 show() { 6 if (this.state === 'show') { 7 alert('已经显示') 8 return 9 } 10 this.state = 'show' 11 console.log('登录框显示成功') 12 } 13 hide() { 14 if (this.state === 'hide') { 15 alert('已经隐藏') 16 return 17 } 18 this.state = 'hide' 19 console.log('登录框隐藏成功') 20 } 21 } 22 23 LoginForm.getInstance = (function () { 24 let instance 25 return function () { 26 if (!instance) { 27 instance = new LoginForm() 28 } 29 return instance 30 } 31 })() 32 33 let obj1 = LoginForm.getInstance() 34 obj1.show() 35 36 let obj2 = LoginForm.getInstance() 37 obj2.hide() 38 39 console.log(obj1 === obj2)
优点:
- 单例模式可以保证内存里只有一个实例,减少了内存的开销。
- 单例模式设置全局访问点,可以优化和共享资源的访问。
- 只会实例化一次。简化了代码的调试和维护
缺点:
- 单例模式一般没有接口,扩展困难
- 有可能导致模块间的强耦合 从而不利于单元测试。
工厂模式
工厂模式定义一个用于创建对象的接口,这个接口由子类决定实例化哪一个类。统一由工厂类来决定具体实例化哪一个类。
1 class Product1 { 2 product() { 3 console.log("生产一线"); 4 } 5 } 6 class Product2 { 7 product() { 8 console.log("生产二线"); 9 } 10 } 11 class Factory { 12 constructor() { 13 this.Product1 = Product1; 14 this.Product2 = Product2; 15 } 16 create(name, callBack) { 17 const product = new this[name](); 18 product.product(); 19 return callBack("susess"); 20 } 21 } 22 let p = new Factory(); 23 p.create("Product1", (res) => { 24 console.log(res); 25 });
优点:
- 工厂职责单一化易于维护
- 有利于消除对象间的耦合,提供更大的灵活性
缺点:添加新产品时,需要编写新的具体产品类,一定程度上增加了系统的复杂度。
代理模式
主要应用:
- ES6 的 proxy
- HTML元 素事件代理
eg:
1 1. 给"ul"标签添加点击事件 2 2. 当点击某"li"标签时,该标签内容拼接"."符号。如:某"li"标签被点击时,该标签内容为".." 3 注意: 4 1. 必须使用DOM0级标准事件(onclick) 5 6 target表示当前触发事件的元素 7 currentTarget是绑定处理函数的元素 8 只有当事件处理函数绑定在自身的时候,target才会和currentTarget一样 9 10 <ul> 11 <li>.</li> 12 <li>.</li> 13 <li>.</li> 14 </ul> 15 16 <script type="text/javascript"> 17 document.querySelector('ul').onclick=event=>{ 18 event.target.innerText+='.' 19 } 20 </script>
装饰器模式
动态地给某个对象添加一些额外的职责,是一种实现继承的替代方案。
1 // 首先我们要创建一个基类 2 function Man(){ 3 4 this.def = 2; 5 this.atk = 3; 6 this.hp = 3; 7 } 8 9 // 装饰者也需要实现这些方法,遵守 Man 的接口 10 Man.prototype={ 11 toString:function(){ 12 return `防御力:${this.def},攻击力:${this.atk},血量:${this.hp}`; 13 } 14 } 15 // 创建装饰器,接收 Man 对象作为参数。 16 var Decorator = function(man){ 17 this.man = man; 18 } 19 20 // 装饰者要实现这些相同的方法 21 Decorator.prototype.toString = function(){ 22 return this.man.toString(); 23 } 24 25 // 继承自装饰器对象 26 // 创建具体的装饰器,也是接收 Man 作对参数 27 var DecorateArmour = function(man){ 28 29 var moreDef = 100; 30 man.def += moreDef; 31 Decorator.call(this,man); 32 33 } 34 DecorateArmour.prototype = new Decorator(); 35 36 // 接下来我们要为每一个功能创建一个装饰者对象,重写父级方法,添加我们想要的功能。 37 DecorateArmour.prototype.toString = function(){ 38 return this.man.toString(); 39 } 40 41 // 注意这里的调用方式 42 // 构造器相当于“过滤器”,面向切面的 43 var tony = new Man(); 44 tony = new DecorateArmour(tony); 45 console.log(`当前状态 ===> ${tony}`); 46 // 输出:当前状态 ===> 防御力:102,攻击力:3,血量:3
优点:
- 方便动态的扩展功能,且提供了比继承更多的灵活性。
缺点:
- 多层装饰比较复杂。
责任链模式
允许你将请求沿着处理者链进行发送。收到请求后,每个处理者均可对请求进行处理,或将其传递给链上的下个处理者。
eg:
促销时针对支付过定金的用户有一定的优惠政策。在正式购买后,已经支付过 500 元定金的用户会收到 100 元的商城优惠券,200 元定金的用户可以收到 50 元的优惠券,而之前没有支付定金的用户只能进入普通购买模式,也就是没有优惠券,且在库存有限的情况下不一定保证能买到。
接收一下三个参数:
orderType
:表示订单类型(定金用户或者普通购买用户),code
的值为 1 的时候是 500 元定金用户,为 2 的时候是 200 元定金用户,为 3 的时候是普通购买用户。pay
:表示用户是否已经支付定金,值为true
或者false
, 虽然用户已经下过 500 元定金的订单,但如果他一直没有支付定金,现在只能降级进入普通购买模式。stock
:表示当前用于普通购买的手机库存数量,已经支付过 500 元或者 200 元定金的用户不受此限制。
1 // 500 元订单 2 var order500 = function (orderType, pay, stock) { 3 if (orderType === 1 && pay === true) { 4 console.log('500 元定金预购, 得到 100 优惠券'); 5 } else { 6 order200(orderType, pay, stock); // 将请求传递给 200 元订单 7 } 8 }; 9 // 200 元订单 10 var order200 = function (orderType, pay, stock) { 11 if (orderType === 2 && pay === true) { 12 console.log('200 元定金预购, 得到 50 优惠券'); 13 } else { 14 orderNormal(orderType, pay, stock); // 将请求传递给普通订单 } 15 }; 16 } 17 // 普通购买订单 18 var orderNormal = function (orderType, pay, stock) { 19 if (stock > 0) { 20 console.log('普通购买, 无优惠券'); 21 } else { 22 console.log('手机库存不足'); 23 } 24 }; 25 // 测试结果: 26 order500(1, true, 500); // 输出:500 元定金预购, 得到 100 优惠券 27 order500(1, false, 500); // 输出:普通购买, 无优惠券 28 order500(2, true, 500); // 输出:200 元定金预购, 得到 500 优惠券 29 order500(3, false, 500); // 输出:普通购买, 无优惠券 30 order500(3, false, 0);// 输出:手机库存不足
优点:
代码结构比较清晰
缺点:
违反开放-封闭原则
应用:
- JS 中的事件冒泡
- 作用域链
- 原型链
观察者模式:
eg: Promise 的执行类似于观察者模式
1 const p1 = new Promise((resolve, reject) => { 2 setTimeout(() => { 3 resolve('result') 4 }, 5 1000); 6 }) 7 8 p1.then(res => console.log(res), err => console.log(err))
分析Promise的调用流程:
- Promise的构造方法接收一个executor(),在new Promise()时就立刻执行这个executor回调
- executor()内部的异步任务被放入宏/微任务队列,等待执行
- then()被执行,收集成功/失败回调,放入成功/失败队列
- executor()的异步任务被执行,触发resolve/reject,从成功/失败队列中取出回调依次执行
观察者模式:收集依赖 -> 触发通知 -> 取出依赖执行
在Promise里,执行顺序是 then收集依赖 -> 异步触发resolve -> resolve执行依赖
。
Promise实现:
1 class MyPromise { 2 // 构造方法接收一个回调 3 constructor(executor) { 4 this._resolveQueue = [] // then收集的执行成功的回调队列 5 this._rejectQueue = [] // then收集的执行失败的回调队列 6 7 /*由于resolve/reject是在executor内部被调用, 8 因此需要使用箭头函数固定this指向, 否则找不到this._resolveQueue*/ 9 10 let _resolve = (val) => { 11 // 从成功队列里取出回调依次执行 12 while(this._resolveQueue.length) { 13 const callback = this._resolveQueue.shift() 14 callback(val) 15 } 16 } 17 // 实现同resolve 18 let _reject = (val) => { 19 while(this._rejectQueue.length) { 20 const callback = this._rejectQueue.shift() 21 callback(val) 22 } 23 } 24 // new Promise()时立即执行executor,并传入resolve和reject 25 executor(_resolve, _reject) 26 } 27 28 // then方法,接收一个成功的回调和一个失败的回调,并push进对应队列 29 then(resolveFn, rejectFn) { 30 this._resolveQueue.push(resolveFn) 31 this._rejectQueue.push(rejectFn) 32 } 33 }
标签:function,resolve,console,log,JS,设计模式,定金,500 From: https://www.cnblogs.com/taue997/p/17364403.html