大体分为三类:简单工厂模式、工厂方法模式、抽象工厂模式。
简单工厂模式 是由一个工厂对象来创建某一类产品的实例比如说,我来到一家书店买书,我要买编程类的书,分别是“JS高级编程,第三版,2013年出版”、“CSS世界,第一版,2017年出版”、“VUE权威指南,第一版,2018年出版”,我不用自己去找这些书,而是口头告诉给店员,让他帮我找,并且告诉我价格。
这时,店员就是这个工厂对象,而返回给我的书的信息以及价格则是这个产品的实例。拿起键盘开始实现:
function bookShop(name,year,vs){ var book=new Object(); book.name=name; book.year=year; book.vs=vs; book.price='暂无标价'; if(name==='js高级编程'){ book.price='79'; } if(name=='css世界'){ book.price='69'; } if(name=='vue权威指南'){ book.price='12'; } return book; } var book1=bookShop('JS高级编程', '2013', '第三版'); var book2=bookShop('ES6入门教程', '2017', '第六版'); var book3=bookShop('css世界', '2015', '第一版'); console.log(book1); console.log(book2); console.log(book3);来康康打印结果:
工厂方法模式与简单工厂模式有些差异,可以理解为升级版的简单工厂模式。 上面简单工厂模式是创建同一类的某个产品,而这里的工厂模式是创建多类产品的实例,其实就是将多个产品进行抽象化。 比如:我不想买编程类的书了,我要买科学类或者社会学类的书,那么工厂方法模式的作用就体现出来了。
function Programe(){ this.books=['css世界','js高级编程','Es6入门'] var text='这里有'; this.books.forEach(function (name){ text+=name+'' }) this.content=text } function NBA(){ this.books=['jamus','curry','kobe'] var text='这里有'; this.books.forEach(function (name){ text+=name+'' }) this.content=text } function History(){ this.books=['秦始皇自传','毛泽东全集','溜冰鞋漂流记'] var text='这里有'; this.books.forEach(function (name){ text+=name+'' }) this.content=text } function bookShop(name){ var book=new Object() book.name=name if(name==='Programe'){ return new Programe() } if(name==='NBA'){ return new NBA() } if(name='History'){ return new History() } } console.log(bookShop('programe')) //输出:**{books: Array(3), content: "这里有css世界 JS高级编程 ES6入门教程 "}**简单工厂模式是创建某一种类的实例,是针对一个类的实例创建,而工厂方法模式是多个类创建实例。
抽象工厂模式是对类的工厂的抽象,用于创建产品类,而不是创建产品类的实例 是面向一个工厂类的产品类,这个工厂再逐步扩大。 举例说明 现有一家电子设备厂,它能生产手机、电视、电脑、平板等电子设备,而手机品牌中又有华为、小米、OPPO等等,电视品牌中有长虹、TCL、海尔等等,电脑有联想、神舟、宏碁等等,平板有联想、华为、小米等等。
好的,现在这个工厂结构就出来了,工厂是电子设备厂,产品类是手机、电脑、电视、平板,实例是每个产品的品牌,而每个品牌有它自己的价格。
但是作为普通消费者,不可能直接到厂家去买一个电子设备,而是在营业厅去购买,存在一个关系链
1.我们首先创建这个电子设备厂以及其产品种类 //厂家接受两个参数分别是产品子类和产品类 var Electonics=function(subType,superType){ //如果产品类在这个厂家中存在,就利用寄生继承方式,让产品子类继承产品类中的所有属性 if(typeof Electonics(superType)==='function'){ var F=function(){} //constructor 属性返回对创建此对象的数组函数的引用。 F.prototype=new Electonics[superType]() subType.constructor=subType subType.prototype=new F() }else{ throw new Error('没有找到'+superType+'抽象类') } } //以下均为产品类 Electonics.phone=function(){ this.type='Phone' } Electonics.Tv=function(){ this.type='Tv' } //直接访问方法抛出错误,是为了不让外部在没重写子类方法之前访问这些方法 //需通过继承产品类之后重写这个方法才能访问 Electonics.Tv.prototype={ getPrice:function(){ return new Error('请先重写子类') } } Electonics.PPC=function(){ this.type='PPC' } Electonics.PPC.prototype={ getPrice:function(){ return new Error('请先重写子类') } } Electonics.Computer=function(){ this.type='Computer' } Electonics.Computer.prototype={ getPrice:function(){ return new Error('请先重写子类') } }营业厅是针对产品类的,它是继承于某个产品类,拥有该产品类的所有属性和方法。 也就是说不可能卖手机的营业厅在卖电视,不可能卖电视的在卖电脑。
2.创建营业厅 //手机产品子类 var Phone=function(name,price){ this.name=name this.price=price } //找厂家进货 Electonics(phone,'phone') //进货后重新标价,即重写价格方法,使顾客可以访问 Phone.prototype.getPrice=function(){ return this.price; } //电视产品子类 var TV=function(name,price){ this.name=name this.price=price } Electonics(TV,'Tv') TV.prototype.getPrice=function(){ return this.price } //电脑产品子类 var Computer=function(name,price){ this.name=name this.price=price } Electonics(Computer,'Computer') TV.prototype.getPrice=function(){ return this.price } //平板产品子类 var PPC=function(name,price){ this.name=name this.price=price } Electonics(PPC,'PPC') TV.prototype.getPrice=function(){ return this.price } 3.开始购买 // 去手机营业厅买手机 var huaw=new Phone('华为',3000) console.log('价钱:'+huaw.getPrice()+',类型'+huaw.type) // 去电视机营业厅买电视 var changh=new TV('长虹',1999) console.log('价钱:'+changh.getPrice()+',类型'+changh.type) // 去电脑营业厅买电脑 var dell=new Computer('dell',6989) console.log('价钱:'+dell.getPrice()+',类型'+changh.type) // 去平板店买平板 var ipad=new PPC('ipad',2999) console.log('价钱:'+ipad.getPrice()+',类型'+changh.type) 4.打印结果 价格:3000,类型:phone 价格:1999,类型:TV 价格:6808,类型:Computer 价格:2999,类型:PPC抽象工厂模式创建了类之后,类的实例会知道自己属于什么类,这也是抽象工厂模式的一大优点