JavaScript设计模式部分理解
单例设计模式:保证一个类仅有一个实例对象,并提供一个访问它的全局访问点.实现的方法为先判断是否存在,如果存在则直接返回,如果不存在就创建后再返回这样确保一个类只有一个实例对象.
个人理解:这还得写个闭包 ,不写的话拿不到内部instance,不然就得全局声明变量,那样不好
let SingleMode = (function(){ let instance = null return function(){ !instance && (instance = new Object) return instance } })()
策略模式:根据不同参数可以命中不同的策略
个人理解:有点类似于对象枚举(可能描述的不对,完全个人理解);减少了大量的if语句
按照demo来看完全可以用参数解决问题,可能策略模式会有更大的作用demo较简单了,理解的也太简单了
let modeObj = { 'A':function(arg){ return arg * 4 }, 'B':function(arg){ return arg * 5 }, 'C':function(arg){ return arg * 6 } } function getMode(mode,arg){ return modeObj[mode](arg) } getMode('A',1000)
代理模式:为一个对象提供一个代用品或占位符以便控制对它的访问
讲解理解:在代理中可实现保护代理和虚拟代理;代理中可以过滤掉一些请求这就是保护代理;虚拟代理则是对于一些开销很大的对象而言,直到真正需要它的时候再去创建
let requestObj = { sendMsg(target){ target.receiveMsg('我想和你说点事') } } let proxyObj = { receiveMsg(msg){ responseObj.receiveMsg(msg) } } let responseObj = { receiveMsg(msg){ console.log(msg) } }
迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素而又不暴露该对象的内部表示
each([1,2,3],cb)这种属于内部迭代器;外部迭代器就不去理解了
发布订阅模式:它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于他的对象都将得到通知
class PubSub {} PubSub.prototype.list = {} PubSub.prototype.on = function (key, callback) { if (!this.list[key]) { this.list[key] = [] } this.list[key].push(callback) } PubSub.prototype.emit = function (key, ...rest) { const callbacks = this.list[key] if (!callbacks || callbacks.length === 0) return callbacks.forEach(callback => callback(...rest)) } PubSub.prototype.remove = function (key, callback) { const callbacks = this.list[key] if (!callbacks || callbacks.length === 0) return fasle for (let i = 0; i < callbacks.length; i++) { const cb = callbacks[i] if (cb === callback) return callbacks.splice(i, 1) } } const lyn = new PubSub() const sh = new PubSub() const zjy = new PubSub() lyn.on('join', (position, salary) => { console.log('你的职位是:' + position); console.log('期望薪水:' + salary); }); lyn.on('other', (skill, hobby) => { console.log('你的技能有:' + skill); console.log('爱好:' + hobby); }); sh.emit('join', '前端', 10000); sh.emit('join', '后端', 10000); zjy.emit('other', '端茶和倒水', '篮球');
基于Object.defineProperty方法
let pubSub = { on(name,fn){ if(!this[name]){ this[name + '_events'] = [] Object.defineProperty(this,name,{ set(args){ if(!this[name + '_events'] || !this[name + '_events'].length){ return } this[name + '_events'].forEach(event => { event.call(this,...args) }) } }) } this[name + '_events'].push(fn) }, emit(name,...args){ this[name] = args } }
命令模式:最常见的应用场景是有时候需要向某些对象发送请求但是并不知道请求的接收者是谁也不知道被请求的操作是什么
个人理解:NP项目web端与移动端采用的外部执行js感觉就是使用的这种设计模式
function command(btn,fn){ btn.onclick = fn } function addFn(){ console.log('点击按钮我就输出111') } command(document.getElementById('btn'),addFn)
模板方法模式:在继承的基础上在父类中定义好执行的公共算法
个人理解:理解好继承我感觉比懂这个设计模式都强
享元模式:是一种优化程序性能的模式,本质是为了减少对象创建的个数
个人理解:这样仅创建两个实例对象,不用创建多个对象执行实例中的方法
function Model(sex){ this.sex = sex } Model.prototype.takePhoto = function(){ console.log(`性别${this.sex},试穿${this.underWear}衣服.`) } var man = new Model('man'),woman = new Model('woman'),arr = [1,2,3,4,5]; arr.map((item)=>{ man.underWear = item woman.underWear = item man.takePhoto() woman.takePhoto() })
职责链模式:通过请求第一个条件会持续执行后续的条件知道返回结果为止
个人理解:可以按照 async await 异步改为同步那种方式理解,但应该不是一回事,demo中讲解是将函数拆分若干个函数从而避免过多if判断,这也可能是为什么当时周斌(久其前同事)看我写的方法叫我尽可能拆分出改写为多个方法的原因
中介者模式:对象和对象之间借助第三方中介者进行通信 再研究研究 demo写的不对 没写完有问题
function add(newobj){ middle.add(newobj) } function Person(name){ this.name = name } Person.prototype.sendMsg = function(){ middle.handleMsg('sendMsg',this) } Person.prototype.receiveMsg = function(){ middle.handleMsg('receiveMsg',this) } var middle = (function(){ var obj = {},doFn = {}; doFn.add = function(newobj){ obj[newobj.name] = obj } doFn.receiveMsg = function(){ console.log(this.name+'接收消息') } doFn.sendMsg = function(){ console.log(this.name+'发送消息') } var handleMsg = function(){ var dothis = Array.prototype.shift.call(arguments) doFn[dothis].apply(this,arguments) } return { handleMsg:handleMsg } })()
装饰者模式:将一个对象嵌入另一个对象之中,实际上相当于这个对象被另一个对象包装起来形成一条包装链,请求随着这条链依次传递到所有的对象,每个对象都有处理这条请求的机会
基本demo
个人理解:fire1和fire2对相当于装饰加的衣服要的话加上不要的话去掉 主体还是plane.fire方法
var plane = { fire:function(){ console.log('发射子弹') } } var fire1 = plane.fire plane.fire = function(){ fire1() console.log('发射导弹') } var fire2 = plane.fire plane.fire = function(){ fire2() console.log('发射原子弹') } plane.fire() //复杂demo 不太理解 先写出来吧 Function.prototype.before = function(beforeFn){ var that = this return function(){ beforeFn.apply(this,arguments) return that.apply(this,arguments) } } Function.prototype.after = function(afterFn){ var that = this return function(){ var ret = that.apply(this,arguments) afterFn.apply(this,arguments) return ret } }
状态模式:区分事务内部的状态,事务内部状态的改变往往会带来事物行为的改变
个人理解:其实定义在外部的用于判断状态的flag有点类似于状态模式
适配者模式:解决两个软件是体检的接口不兼容的问题
个人理解:兼容不同第三方插件中调用的方法还可以处理数据格式兼容
var GaodeMap = { show:function(){ console.log('高德地图渲染') } } var BaiduMap = { block:function(){ console.log('百度地图渲染') } } var BaiduMapAdapter = { show:function(){ BaiduMap.block() } } var renderMap = function(map){ if(map.show instanceof Function){ map.show() } }
以自己现在的努力程度,还没有资格和别人拼天赋