javascript设计模式及应用场景
栏目: JavaScript · 发布时间: 5年前
内容简介:这里花几分钟时间来讲解几个设计模式以及它们的应用场景。可以帮助你在平时开发时把设计模式用起来废话不多说,直接上demo目前浏览器不支持装饰器模式,如果想要让这段代码跑起来的话,需要依赖babel的一个插件:babel-plugin-transform-decorators-legacy
这里花几分钟时间来讲解几个 设计模式 以及它们的应用场景。可以帮助你在平时开发时把设计模式用起来
- 装饰器模式
- 迭代器模式
- 发布订阅模式
- 工厂模式
- 单例模式
- 代理模式
- 外观模式
废话不多说,直接上demo
装饰器模式
装饰器DEMO
<!--index.js--> function decoratorHoc(target){ target.customerName = 'xuqiang'; } @decoratorHoc class Person{} console.log(Person.customerName); 复制代码
装饰器疑问 ️
- decoratorHoc是个函数,为何支持@decoratorHoc?不要把这个当作理所当然。可以试下把代码拷入vscode,然后code runner,发现报了这段错
目前浏览器不支持装饰器模式,如果想要让这段代码跑起来的话,需要依赖babel的一个插件:babel-plugin-transform-decorators-legacy
那么下面三步来把babel环境搞一下
- 安装全局babel
<!--在当前index.js目录下--> yarn add babel-cli -g yarn add babel-plugin-transform-decorators-legacy 复制代码
- 配置.babelrc
<!--在当前index.js目录下新建.babelrc文件,内容如下--> { plugins: ['transform-decorators-legacy'] } 复制代码
- 编译index.js
<!--在当前index.js目录下--> babel index.js --out-file compiled.js 复制代码
这里把index.js编译为了compiled.js。然后code runner compiled.js,发现日志输出了"xuqiang"
至此你就实现了装饰器decoratorHoc
装饰器模式应用场景
装饰器模式可以说是非常方便地扩展了一个对象。那么平时开发中是不是有几类代码跟装饰器模式很相似
- react的高阶组件
- dva的@connect
这里就举两个例子,更多场景需要你自己去发现了
迭代器模式
迭代一个对象,就可以称为是迭代器,下面从es6的迭代器来讲解下
for-of遍历json
这是一个es6的自定义迭代器DEMO,讲解如何写一个迭代器来遍历普通对象,因为遍历数组内置已经支持了
let obj = { name: 'xuqiang', age: 20, [Symbol.iterator]: () => { let props = Object.keys(obj), i = props.length; return { next(){ if(i > 0){ i = i - 1; return { value: obj[props[props.length - i - 1]], done: false }; }else{ return { value: '', done: true }; } } }; } } for(let prop of obj){ console.log(prop); } 复制代码
code runner发现可以正确遍历一个Object了
发布订阅模式
发布订阅的场景
用一个老生常谈的场景先来解释下发布订阅,那就是学生时代的订牛奶,先来整理下需求
- 有一个工厂,有一个let products = {},有一种属性叫做牛奶。此属性对应一个数组,数组存储每个订奶牛人的数据。
- 工厂有一个定时器,每天早上8点开始遍历products,进行牛奶派发
- 有很多消费者,向工厂订牛奶
需求整理清楚了,下面用个DEMO来实现下
// 发布订阅模式 // 发布订阅模式 class Puber{ constructor(name){ this.name = name; this.products = {}; this.startInterval(); } startInterval(){ setInterval(() => { for(let prop in this.products){ if(this.products.hasOwnProperty(prop)){ this.emit(prop); } } }, 3000); } sub(evt, cb){ if(!this.products[evt]){ this.products[evt] = []; } this.products[evt].push(cb); } emit(evt){ if(this.products[evt]){ let cbs = this.products[evt]; for(let cb of cbs){ cb && cb(); } } } } class Suber{ constructor(name){ this.name = name; this.puber = new Puber('徐强'); } getPuber(){ console.log(`我是${this.name},我的牛奶配送员是${this.puber.name}`); } sub(evt, cb){ this.puber.sub(evt, cb); } } let customer1 = new Suber('刘思琪'); customer1.getPuber(); customer1.sub('牛奶', () => { console.log(`现在时间是${+new Date},牛奶送至未来科技城,收件人:刘思琪`); }); let customer2 = new Suber('徐大佬'); customer2.getPuber(); customer2.sub('牛奶', () => { console.log(`现在时间是${+new Date},牛奶送至空港新城,收件人:徐大佬`); }); 复制代码
发现刘思琪和徐大佬,已经成功订了牛奶,并且每天早上10点钟开始派发牛奶了。当然了,这里没有写取消订牛奶的操作,大家可以自己接着写
工厂模式
class jQuery{ constructor(name){ this.name = name; } } function $(name){ return new jQuery(name); } let obj1 = $('xuqiang'); let obj2 = $('liusiqi'); console.log(obj1); console.log(obj2); 复制代码
工厂模式总结
这里举例也是用的jquery,可以发现jquery的$函数就是用了工厂模式,那么工厂模式有哪些好处呢?
- 不需要自己调用new jQuery。直接用$很方便
- 类似React.createElement,屏蔽了开发者直接使用new VNode,符合开放封闭原则,VNode的实现对开发者不可见
单例模式
光是单例模式的话比较简单,感觉没什么亮点,所以这里结合装饰器模式来写一个单例模式
写一个装饰器模式+单例模式的骚操作
function getInstanceHoc(target){ target.getInstance = (() => { let instance; return () => { if(!instance){ instance = new Function(`return new ${target}()`)(); } return instance; } })(); } @getInstanceHoc class Person{ eat(){ console.log('i am eating'); } } let obj = Person.getInstance(); console.log(obj); obj.eat(); let obj1 = Person.getInstance(); console.log(obj === obj1); 复制代码
code runner之后发现,obj和obj1都可以eat了,然后比较obj===obj1,发现是true,说明单例模式已经成功了
代理模式
用es6的Proxy来讲一下代理
class Vue{ constructor(data){ let _data = data; return new Proxy(this, { get(target, key){ return _data[key]; }, set(target, key, val){ _data[key] = val; } }); } } let obj = new Vue({ name: '徐强', age: 20 }); console.log(obj.name); obj.name = '刘思琪'; console.log(obj.name); 复制代码
外观模式
外观模式在jquery中很常见。在我们平时开发中感觉也很好用
function winAlert(title, message, buttons, cb){ if(cb === undefined){ cb = buttons; buttons = null; } console.log(title); console.log(message); console.log(buttons); console.log(cb); } winAlert('提示', '操作完成', ['确认', '取消'], () => {}); winAlert('提示', '操作完成', () => {}); 复制代码
运行结果:
这让我想起目前业务中后端所有接口都是app/htmlGateway.do,只是version,rd等参数区别,从某种角度来说这是符合外观模式的。封闭后端api的内部实现,开放htmlGetway给前端调用
但是目前这种方式有个问题是,对于yapi,rap2等mock平台不太友好。因为api路径都是一致的,会不太好mock,也可能是因为我没有发现解决方案吧,所以觉得不太好mock
ok 这几种设计模式的demo都已经讲完了。有问题可以一起谈论。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 真实项目案例实战—【状态设计模式】使用场景
- 重学 Java 设计模式:实战模版模式「模拟爬虫各类电商商品,生成营销推广海报场景」
- 重学 Java 设计模式:实战策略模式「模拟多种营销类型优惠券,折扣金额计算策略场景」
- 重学 Java 设计模式:实战备忘录模式「模拟互联网系统上线过程中,配置文件回滚场景」
- 重学 Java 设计模式:实战观察者模式「模拟类似小客车指标摇号过程,监听消息通知用户中签场景」
- 重学 Java 设计模式:实战访问者模式「模拟家长与校长,对学生和老师的不同视角信息的访问场景」
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Algorithms to Live By
Brian Christian、Tom Griffiths / Henry Holt and Co. / 2016-4-19 / USD 30.00
A fascinating exploration of how insights from computer algorithms can be applied to our everyday lives, helping to solve common decision-making problems and illuminate the workings of the human mind ......一起来看看 《Algorithms to Live By》 这本书的介绍吧!