首页 > 其他分享 >JS 设计模式

JS 设计模式

时间:2023-04-29 19:44:17浏览次数:27  
标签:function resolve console log JS 设计模式 定金 500

单例模式

一个类只有一个实例,并提供一个访问它的全局访问点。

 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

相关文章

  • js封装深拷贝方法
    deepCopy:function(data){ if(data===null||data===undefined){ returnnull; } letresult=Array.isArray(data)?[]:{}; if(data&&typeofdata==='object'){ for(letkeyindata){ if(data[key]&&typeof......
  • js循环调用接口,获取每一次接口的值
    vue代码。data数据:list:[{listName:"待办",listNum:0},{listName:"退回",listNum:0},{listName:"已办",listNum:0},{listName:"全部",listNum:0}],methods里面的方法:asyncgetAllData(){this.list.map((listItem,index)=&......
  • Selenium 和 PhantomJS 结合在一起,就可以运行一个非常强大的网络爬虫
    Selenium和PhantomJS结合在一起,就可以运行一个非常强大的网络爬虫   测试人员的最佳11种开源自动化Selenium1)RobotFrameworkRobotFramework是一个开源自动化系统,它使用关键字驱动的方法进行验收测试驱动开发(ATDD)和验收测试。该工具组织了各种测试自动化要求......
  • mapbox加载geojson报错error: Style is not done loading
    Mapbox加载GeoJSON地图时,遇到error:Styleisnotdoneloading错误通常是由于地图样式文件没有加载完成引起的。具体来说,可能是因为Mapbox样式文件中包含了某些需要加载的图片或者矢量图层,而这些图片或矢量图层尚未完全加载完成,导致无法渲染地图。为解决此问题,可以尝试以......
  • 【Python】【MySQL】Python将JSON数据以文本形式存放到MySQL的Text类型字段中
    1.起因在做一个自动打卡的玩意。登录会得到那个平台一系列的信息。我又不想专门修改、增加数据库字段来存放,所有打算直接将返回的JSON数据保存到一个MySQL字段中。内容肯定不能直接放,考虑下比如数据注入的问题,对吧,容易出问题,所有我是打算将JSON数据转为base64编码的格式。先写......
  • node.js用ffmpeg切rtsp实时视频流为mp4,并且在网页上播放
    用express.js框架,这部分太简单了,省略npm或者yarn安装fluent-ffmpeg路由部分代码:router.rtspTrackingHandle=function(req,res){logger.info('[tracking]:rtsphandle');leturl=req.query.url||'';//leturl='rtsp://admin:jeewey123@19......
  • Ext.ux.GMapPanel.js组件的使用 示例
    Ext.ux.GMapPanel.js组件的使用示例 效果: 创建调用的html:<html><head><metahttp-equiv="Content-Type"content="text/html;charset=utf-8"><title>GMapWindowExample</title><linkrel="stylesheet"type=&......
  • 使用localXHR.js让ExtJS docs可以在本地浏览
    使用localXHR.js让ExtJSdocs可以在本地浏览     我们在使用ext/docs目录下的文档时报一些js的错误,导致我们不能正常浏览使用,这时我们使用localXHR.js这样一个文件来支持本地使用ajax,使用方法如下:     下载localXHR.js放在docs目录下,然后在index.html中加入<scriptsrc......
  • JS获取table中选中某几行其中某一列数值的总和
    JS获取table中选中某几行其中某一列数值的总和一、思路1.如何获取某几行,并且可以实时变化数值?实现如下:$("input[type='checkbox']").click(function(){alert($(this).val());})2.接下来就是实现当每次触发点击事件以后,然后,计算其中的值,实现如下:<script>$(functi......
  • 关于json文件想要添加注释怎么处理
    json格式本身不支持注释,json的本意就是极简的通用数据传输。加了备注就不是极简了。1.注释用来说明这个key做什么用2.希望添加注释之后,不会影响原本的交互逻辑。比较好的方法是:json文件里面额外增加一个key"key_comment"用来描述这个key的作用。但是如果本来json文件只是一个......