我要分享的几种设计模式目前的模式:工厂模式、单例模式、适配器模式、装饰者模式、建造者模式建造者模式简介:建造者模式(builderpattern)比较简单,就是一种创作模式。大白话:4个部分:有产品,有能做产品的工厂,有设计师指挥做多少,有想买产品的人。购买产品的用户不介意产品的制造工艺,他们只需要产品!functionCola(){this.sugar='50g',this.water='100g'}functionPacking(){//第一种打包方法this.createPkg=function(){console.log('制作可乐皮')}this.pushCola=function(){console.log('可乐倒入瓶中')}this.complete=function(){varcola=newCola()cola.complete=truereturncola}this.init=function(){this.createPkg()//创建外壳this.pushCola()//倒入瓶中//还可以添加其他步骤returnthis.complete()//完成}}functiongreenPacking(){//绿皮可乐包装方法this.createPkg=function(){console.log('创建绿皮可乐')}this.pushCola=function(){console.log('可乐倒入绿瓶中')}this.complete=function(){varcola=newCola()cola.complete=truereturncola}this.init=function(){this.createPkg()//创建皮肤this.pushCola()//倒入intothebottle//你还可以添加其他步骤returnthis.complete()//生产完成}}functionBoss(){this.createCola=function(packType){constpack=newwindow[packType]this.product=pack.init()//完成产品输出}this.getCola=function(packType){this.创建可乐(包装类型);returnthis.product}}constboss=newBoss()varUserCola=boss.getCola('greenPacking')//UserCola.complete===true不需要别的,只要最后生产出好的可乐即可,有了糖和水,关键在于Boss函数,负责一个整合。同样的Boss功能,通过改变Packing功能和包装方式,可以获得不同风格的可乐。通过将不同的期望参数传递给getCola函数,可以获得不同的最终产品。实现了一个可插入的函数结构。装饰器模式参考前端手写面试题详解装饰器提供了一种更灵活的继承替代方案。装饰器用于包装相同接口的对象,不仅可以让你给方法添加行为,还可以设置方法调用原始对象(比如装饰器的构造函数)。装饰器用于以重载方法的形式添加新功能。这种模式可以在被装饰对象之前或之后添加自己的行为来达到特定的目的。好处:装饰器是实现继承的替代方法。当脚本运行时,向子类添加行为将影响原始类的所有实例,而装饰器则不会。相反,它可以分别为不同的对象添加新的行为。函数iwatch(){this.battery=100;this.getBattery=function(){console.log(this.battery)}}iwatch.prototype.getNewPart=function(part){this[part].prototype=this;//将这个对象上的属性指向新对象的原型returnnewthis[part];//返回一个新的对象,不修改原对象,添加新的对象属性}iwatch.prototype.addNetwork=function(){this.network=function(){console.log('network')}}iwatch.prototype.addSwim=function(){this.swim=function(){console.log('swim')}}varwatch=newiwatch();watch.getBattery();//100watch=watch.getNewPart('addNetwork');//添加新行为,network()watch=watch.getNewPart('addSwim');//network方法和swim方法引入了ES7中的@decorator装饰器提议,参考阮一峰的文章。@testableclassMyTestableClass{//...}functiontestable(target){target.isTestable=true;}MyTestableClass.isTestable//true可以直接使用,装饰器行为@decoratorclassA{}//等同于classA{}A=装饰器(A)||A;工厂模式一个工厂可以生产很多不同的产品,最常见的工厂函数是jQ的$()函数,每个函数的结果是一个需要的产品。functionProduct(name){this.name=name;}Product.prototype.init=function(){console.log('init');}Product.prototype.go=function(){console.log('go');}functionFactory(){}Factory.prototype.add=function(name){returnnewProduct(name);}//useletf=newFactory();leta=f.add('a');console.log(a.name);a.init();a.go();Adapter模式Adapter,将一个类(对象)的一个接口(方法或属性)转换成另一个接口以满足用户需求,从而类(对象)之间的接口不兼容由适配器解决Walk=function(){thrownewError("必须覆盖此方法!")}functionDog(){}Dog.prototype.Walk=function(){thrownewError("必须覆盖此方法!")}Dog.prototype.shout=function(){thrownewError("Thismethodmustbeoverridden!")}functionPersonA(){Person.apply(this)}PersonA.prototype=newPerson()PersonA.prototype.Say=function(){console.log('Personsay')}PersonA.prototype.Walk=function(){console.log('PersonWalk')}functionDogBlack(){Dog.apply(this)}DogBlack.prototype=newDog()DogBlack.prototype.Walk=function(){console.log('DogWalk')}DogBlack.prototype.shout=function(){console.log('DogShout')}//现在希望Dog类也能学习Say,多走几步functionDogSayAdapter(DogClass){Dog.apply(this)this.DogClass=DogClass}DogSayAdapter.原型=newDog()DogSayAdapter.prototype.Say=function(){this.DogClass.shout()}DogSayAdapter.prototype.Walk=function(){this.DogClass.Walk()this.DogClass.Walk()}varpersonA=newPersonA()vardogBlack=newDogBlack()vardogSay=newDogSayAdapter(dogBlack)personA.Say()personA.Walk()dogBlack.Walk()dogBlack.shout()dogSay.Say()dogSay.Walk()//walk*2适配器不仅仅是一个函数接口,也是对数据格式的一种适配。前后端传输数据时常用适配器模式,即通俗易懂的格式化数据、格式化函数等,Vue的计算属性也是适配器模式的一种实现constoriginData=[{title:'title',年龄:18,内容:['123',321],回调:function(){console.log(this)}},{title:'title2',年龄:1,内容:['1',3],回调:function(){console.log('title2')}}]functiondataAdapter(data){returndata.map(item=>{return{title:item.title,content:item.content.join(','),init:item.callback}})}varformatData=dataAdapter(originData)e.g:原始数据的数据不符合当前要求,通过适配器,将数据格式化成想要的格式,不改变原始数据单例模式functionSimple(name){this.name=name}Simple.prototype.go=function(){this.name='go'console.log(this.name)}//static静态方法Simple.getInstance=(function(){varinsreturnfunction(name){if(!ins){ins=newSimple(name)}returnins}})()leta=Simple.getInstance('a')//name:aletb=Simple.getInstance('b')//name:ab===a//true在非单例模式下,同样newSimple()构造函数,不相等,只通过闭包创建一次Simple实例,大家共享一个。懒单例模式懒惰类似于懒加载lazyload,懒加载,或者说需要的时候才加载,否则一次加载太多,频繁操作dom影响性能虽然上面的代码有一个Simple.getInstance方法,但是可以在需要的时候实例化,但仍然不是一个好的实施。可以提取延迟加载的部分。例如:varsimple=function(fn){varinstance;返回函数(){返回实例||(instance=fn.apply(this,arguments));}};//创建遮罩层varcreateMask=function(){//创建div元素varmask=document.createElement('div');//设置样式mask.style.position='fixed';mask.style.top='0';......文档。body.appendChild(面具);//点击隐藏遮罩层mask.onclick=function(){this.style.display='none';}returnmask;};//创建一个登录窗口varcreateLogin=function(){//创建div元素varlogin=document.createElement('div');//设置样式login.style.position='fixed';login.style.top='50%';......login.innerHTML='登录';document.body.appendChild(登录);返回登录名;};document.getElementById('btn').onclick=function(){varoMask=simple(createMask)();oMask.style.display='块';varoLogin=simple(createLogin)();oLogin.style.display='block';}总结学习五种常见的设计模式,这几个类型经常用到,我会继续学习其他18种设计模式。一些设计模式在实际打字中不一定会用到。学习没有坏处,总能派上用场!网上关于设计模式的文章层出不穷,但不管你看多少,还是自己去理解为好,而且在实际使用中,往往会把几种设计模式一起使用。如果不是自己写,看懂了,可能就通俗了。我无法理解设计模式。太可惜了。代码干净整洁,说不出有什么好处。就是看着舒服,赏心悦目,跑得快……
