策略模式:个人感觉就是简单的将不同的方法封装起来,对外暴露一个统一的入口,这样方便使用不同的逻辑。
class choiceItem { static getMoney(type, base) { switch(type) { case 's' : return this.sType(base); case 'a' : return this.aType(base); case 'b' : return this.bType(base); } } static sType(base) { return 6*base; } static aType(base) { return 4*base; } static bType(base) { return 2*base; } } console.log(choiceItem.getMoney('s', 1000));
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
代理模式:作为比较经典的模式应用起来其实并不困难,原理大概就是委托另一方去做某件事情。这个另一方可以增加某些判断,也就是说在不修改原有逻辑的前提下又增加了某些特定功能,例如最最经典的图片代理缓存。
class imgLoad{ constructor(url, loUrl, dom, proxy) { this.url = url; this.proxy = proxy; this.dom = dom; this.loUrl = loUrl; if(this.proxy) { this.isIma = this.isImage(); this.proxyIma = this.proxyImage(); this.proxyIma.setSrc.call(this, this.url); } else { this.isIma = this.isImage(); this.isIma.setSrc.call(this, this.url); } } isImage() { // 正常图片添加区域 const img = new Image(); this.dom.appendChild(img); return { setSrc(url) { img.src = url; } } } proxyImage() { // 缓存图片 const img = new Image(); img.onload = () => { this.isIma.setSrc(this.url); } return { setSrc: function(url) { img.src = url; this.isIma.setSrc(this.loUrl); } } } } new imgLoad('http://ali-static.game.yximgs.com/bs2/fes/game_1571312642677_.png', 'http://ali-static.game.yximgs.com/bs2/fes/game_1571311087230_.png', document.body, true);
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
发布订阅者模式:实际上就是js中的event,注册一个事件,然后在某个特定时间点进行触发,很多的框架使用的时候都利用了这个方法,例如vue组件间触底方法的时候实际上就是这个发布订阅者模式生成的效果。
class Event { constructor() { this.eventList = {}; } on(type, fn) { if(!this.eventList[type]) { this.eventList[type] = []; } this.eventList[type].push(fn); } emit() { const type = Array.prototype.shift.call(arguments); const arr = this.eventList[type]; for(let i in arr) { arr[i].apply(arr[i], arguments); } } } const ev1 = new Event(); ev1.on('ceshi', function(a,b,c) { console.log(a); console.log(b); console.log(c); }) ev1.emit('ceshi', '1111', '2222', '3333');
注意上方代码实际上并没有完全实现on、emit触发,如果触发在on之前的话就会出错。作为容错处理可以在emit中每次触发如果不存在时,将其保存在一个队列中,然后再on中注册是检查是否存在该新增的,然后进行触发,当然这只是简单的逻辑,其中肯定也要包括更多各种各样的容错处理。在此就不多说了。
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
职责链模式:一个理解起来蛮简单,实现起来稍微麻烦点的模式。这个模式主要用于将类似,但是职责不同的代码分开。核心在于,每个当前处理自己阶段的方法,不关心下一个方法处理的具体内容。利用链式处理将多个判断来进行分化。
例如我们想要提取166块钱。那么首先是先扣除面额为100元的钱,然后扣除面额为50,依次类推直到将所有的钱都计算成不同面额现金吐出。
class moneySize { // 生成面额不同的钱 constructor(size) { this.size = size; this.next = null; } getMoney(money) { const floorMoney = Math.floor(money / this.size); if(floorMoney > 0) { console.log(this.size+'元:此处吐出'+floorMoney*this.size); money = money - (floorMoney*this.size); } money>0 && this.next && this.next.getMoney(money); } setNext(next) { this.next = next; } } class ATM { // atm机,主要进行职责链的拼接,以及金额的设定 constructor() { this.money100 = new moneySize(100); this.money50 = new moneySize(50); this.money20 = new moneySize(20); this.money10 = new moneySize(10); this.money1 = new moneySize(1); this.money100.setNext(this.money50); this.money50.setNext(this.money20); this.money20.setNext(this.money10); this.money10.setNext(this.money1); this.first = this.money100; } setMoney(money) { this.first.getMoney(money); } } const atm = new ATM(); atm.setMoney(166);
需要注意的是,职责链模式虽然可以无限拼接。但是在处理的时候造成比较大浪费,例如我们假设想要获取6元钱,那么它会浪费掉前期的100、50等等面额的计算,最终确定在1元的金额进行处理。所以这个本身是存在浪费的,所以在使用时需要注意这个。