时间:2021-05-26
本文实例讲述了JavaScript设计模式--简单工厂模式定义与应用。分享给大家供大家参考,具体如下:
工厂模式创建对象(视为工厂里的产品)时无需指定创建对象的具体类。
工厂模式定义一个用于创建对象的接口,这个接口由子类决定实例化哪一个类。该模式使一个类的实例化延迟到了子类。而子类可以重写接口方法以便创建的时候指定自己的对象类型。
在这里将工厂简单分为三种:
(1)简单工厂:通过第三方的类完成松耦合的任务。
(2)复杂工厂:通过把实例化的任务交给子类来完成的,用以到达松耦合的目的。
(3)超级工厂:通过eval()来完成智能工厂。
工厂的目的:在于判断接口最终用哪个类实例化(故与接口密不可分)。
使用工厂最终达到的效果是:多态,和类与类之间的松耦合。
工厂模式与接口是密不可分的所以我们需要先引入接口文件和继承类文件
(1)接口文件:
(2)继承文件
//subClass:子类 superClass:超类function extend(subClass,superClass) { //1,使子类原型属性等于父类的原型属性 //初始化一个中间空对象,目的是为了转换主父关系 var F = function () {}; F.prototype = superClass.prototype; //2, 让子类继承F subClass.prototype = new F(); subClass.prototype.constructor = subClass; //3,为子类增加属性 superClass ==》原型链的引用 subClass.superClass = superClass.prototype; //4,增加一个保险,就算你的原型类是超类(Object)那么也要把你的构造函数级别降下来 if (superClass.prototype.constructor == Object.prototype.constructor) { superClass.prototype.constructor = superClass; }}通过下面的例子,逐步引进工厂模式及改进工厂模式
1,工厂模式的引入,
(1)创建接口对象
(2)定义一个宠物店类并在prototype上进行扩展
(3)分析宠物的一些特点可以将一些公共的部分提取出来(这里只是简单的提取)
//基类 有共同的提出来 function basePet() { this.register=function () { document.write("宠物登记...<br>"); } this.eat=function () { document.write("宠物吃饭...<br>"); } }(4)各个实现类 ---这里是各种动物
function Dog() { Dog.superClass.constructor.call(this);//继承父类 //实现接口部分 this.run=function () { document.write("小狗跑......<br>") } this.sing=function () { document.write("小狗唱歌......<br>") } } function Cat() { Cat.superClass.constructor.call(this);//继承父类 //实现接口部分 this.run=function () { document.write("小猫跑......<br>") } this.sing=function () { document.write("小猫唱歌......<br>") } } function Pig() { Pig.superClass.constructor.call(this);//继承父类 //实现接口部分 this.run=function () { document.write("小猪跑......<br>") } this.sing=function () { document.write("小猪唱歌......<br>") } } function Bird() { Bird.superClass.constructor.call(this);//继承父类 //实现接口部分 this.run=function () { document.write("小鸟跑......<br>") } this.sing=function () { document.write("小鸟唱歌......<br>") } }(5)各个实现类继承基类
//继承(6)创建宠物的开始卖宠物
var newPetShop=new PetShop(); var flowerPig=newPetShop.sellPet("pig"); flowerPig.run();结果为:
总结一下,上述好像没怎么体现有关工厂之类的,我们应该注意到这么一个问题就是:当需要增加一个新品种宠物时,我们需要修改 '宠物店类',耦合度较高。
为了解决这个问题我们使用简单工厂模式来解决。
2,简单工厂模式(针对上述的改进)
(1)接口文件与继承文件的的引入 同上面
(2)静态工厂
//使用工厂方式创建宠物对象 // 静态工厂 var factoryPet={ //出售宠物的方法 getPet:function (kind) { //宠物对象 var pet; //宠物种类 switch (kind){ case 'dog': pet=new Dog(); break; case 'cat': pet=new Cat(); break; case 'pig': pet=new Pig(); break; default: pet=new Bird(); } //验证接口 Interface.ensureImplement(pet,Pet);//判断pet对象是否全部实行接口Pet里面全部的方法 return pet; } }(3)利用工厂创建宠物店对象
var factoryPetShop=function () {} factoryPetShop.prototype={ getPet:function (kind) { var pet=factoryPet.getPet(kind); pet.eat(); pet.register(); return pet; } }(4)从宠物店购买宠物实现
var newPetShop=new factoryPetShop(); var flowerCat=newPetShop.getPet("cat"); flowerCat.sing();(5)使用简单工厂实现的全部代码(数字标号表示其思考的先后顺序)
(function () { //(2)接口调用 var Pet=new Interface("Pet",["eat","run","sing","register"]); //(3)基类 分析后有共同的提出来作为基类 function basePet() { this.register=function () { document.write("宠物登记。。。。<br>"); } this.eat=function () { document.write("宠物吃饭。。。。<br>"); } } //(4)实现类 继承基类+接口实现 function Dog() { Dog.superClass.constructor.call(this);//继承父类 //实现接口 this.run=function () { document.write("小狗跑......<br>") } this.sing=function () { document.write("小狗唱歌......<br>") } } function Cat() { Cat.superClass.constructor.call(this);//继承父类 //实现接口 this.run=function () { document.write("小猫跑......<br>") } this.sing=function () { document.write("小猫唱歌......<br>") } } function Pig() { Pig.superClass.constructor.call(this);//继承父类 //实现接口 this.run=function () { document.write("小猪跑......<br>") } this.sing=function () { document.write("小猪唱歌......<br>") } } function Bird() { Bird.superClass.constructor.call(this);//继承父类 //实现接口 this.run=function () { document.write("小鸟跑......<br>") } this.sing=function () { document.write("小鸟唱歌......<br>") } } //继承 extend(Dog,basePet); extend(Cat,basePet); extend(Pig,basePet); extend(Bird,basePet); //(1)使用工厂方式创建宠物对象 // 静态工厂 var factoryPet={ //出售宠物的方法 getPet:function (kind) { //宠物对象 var pet; //宠物种类 switch (kind){ case 'dog': pet=new Dog(); break; case 'cat': pet=new Cat(); break; case 'pig': pet=new Pig(); break; default: pet=new Bird(); } //验证接口 Interface.ensureImplement(pet,Pet);//判断pet对象是否全部实行接口Pet里面全部的方法 return pet; } } //(5)利用工厂的宠物店对象(宠物店买宠物) var factoryPetShop=function () {} factoryPetShop.prototype={ getPet:function (kind) { var pet=factoryPet.getPet(kind); pet.eat(); pet.register(); return pet; } }//(6)从宠物店购买宠物 var newPetShop=new factoryPetShop();//宠物工厂 var flowerCat=newPetShop.getPet("cat");//从宠物工厂中得到宠物 flowerCat.sing();})()总结一下,上述看似完美,但是任有问题存在:比如说:张三的宠物店想卖哈士奇,李四的宠物店想卖鸟时,这样的话,宠物都是通过一个工厂生产的,并不一定满足各个卖家的需求。
所以我们需要根据各个厂家的需求,有不同的工厂,各个卖家可以根据自己需求使用不同的工厂(其实是利用不同子类实现各自合适的工厂),用于满足每个宠物店的不同。
于是我们有了复杂的工厂用来解决该问题。
3,复杂工厂:通过把实例化的任务交给子类来完成的,用以到达松耦合的目的。
此处同样是根据上述进行改进的,还是简单的说明一下实现过程
(1)在html中将接口文件的引进,代码为
//定义一个静态方法来实现接口与实现类的直接检验//静态方法不要写出Interface.prototype ,因为这是写到接口的原型链上的//我们要把静态的函数直接写到类层次上//定义一个接口类var Interface=function (name,methods) {//name:接口名字 if(arguments.length<2){ alert("必须是两个参数") } this.name=name; this.methods=[];//定义一个空数组装载函数名 for(var i=0;i<methods.length;i++){ if(typeof methods[i]!="string"){ alert("函数名必须是字符串类型"); }else { this.methods.push( methods[i]); } }};Interface.ensureImplement=function (object) { if(arguments.length<2){ throw new Error("参数必须不少于2个") return false; } for(var i=1;i<arguments.length;i++){ var inter=arguments[i]; //如果是接口就必须是Interface类型 if(inter.constructor!=Interface){ throw new Error("如果是接口类的话,就必须是Interface类型"); } //判断接口中的方法是否全部实现 //遍历函数集合 for(var j=0;j<inter.methods.length;j++){ var method=inter.methods[j];//接口中所有函数 //object[method]传入的函数 //最终是判断传入的函数是否与接口中所用函数匹配 if(!object[method]||typeof object[method]!="function" ){//实现类中必须有方法名字与接口中所用方法名相同 throw new Error("实现类中没有完全实现接口中的所有方法") } } }}(2)在html中将继承文件引入,代码如下,
//subClass:子类 superClass:超类function extend(subClass,superClass) { //1,使子类原型属性等于父类的原型属性 //初始化一个中间空对象,目的是为了转换主父关系 var F = function () {}; F.prototype = superClass.prototype; //2, 让子类继承F subClass.prototype = new F(); subClass.prototype.constructor = subClass; //3,为子类增加属性 superClass ==》原型链的引用 subClass.superClass = superClass.prototype; //4,增加一个保险,就算你的原型类是超类(Object)那么也要把你的构造函数级别降下来 if (superClass.prototype.constructor == Object.prototype.constructor) { superClass.prototype.constructor = superClass; }}(3)分析各个类提出相同的部分作为基类,基类代码如下
//基类 分析后有共同的提出来作为基类 function basePet() { this.register=function () { document.write("宠物登记。。。。<br>"); }; this.eat=function () { document.write("宠物吃饭。。。。<br>"); } }(4)各个具体的实现类:继承基类+接口实现
//各个宠物类(实现类) 继承基类+接口实现 function Dog() { Dog.superClass.constructor.call(this);//继承父类 //实现接口 this.run=function () { document.write("小狗跑......<br>") } this.sing=function () { document.write("小狗唱歌......<br>") } } function Cat() { Cat.superClass.constructor.call(this);//继承父类 //实现接口 this.run=function () { document.write("小猫跑......<br>") } this.sing=function () { document.write("小猫唱歌......<br>") } } function Pig() { Pig.superClass.constructor.call(this);//继承父类 //实现接口 this.run=function () { document.write("小猪跑......<br>") } this.sing=function () { document.write("小猪唱歌......<br>") } } function Bird() { Bird.superClass.constructor.call(this);//继承父类 //实现接口 this.run=function () { document.write("小鸟跑......<br>") }; this.sing=function () { document.write("小鸟唱歌......<br>") } }(5)实现类与基类的继承实现,代码如下(调用extend())
extend(Dog,basePet);//动物狗继承基类 extend(Cat,basePet); extend(Pig,basePet); extend(Bird,basePet);(6)将商店抽取出来,做成抽象类,代码如下
//把核心商店抽取出来 var petShop=function () {}; petShop.prototype={//模拟抽象类 需要被子类覆盖 getPet:function (kind){ var pet=this.getpet(kind); pet.eat(); pet.register(); return pet; }, getpet:function (model){ throw new Error("该类是抽象类,不能实例化") } };(7)利用子类来满足各个商家的不同类型宠物店的实现 ,代码如下
//利用子类来满足之前的需求(多态) var oneShop=function () { } extend(oneShop,petShop);//继承 //覆写方法 oneShop.prototype.getpet=function (model) { //宠物对象 var pet; //宠物种类 switch (model){ case 'dog': pet=new Dog(); break; default: pet=new Bird(); } //验证接口 Interface.ensureImplement(pet,Pet);//判断pet对象是否全部实行接口Pet里面全部的方法 pet.eat(); pet.register(); return pet; };同上,这个也是一个不同的子类
twoShop=function () {}; extend(twoShop,petShop);//商店的继承 //覆写方法 twoShop.prototype.getPet=function (model) { //宠物对象 var pet; //宠物种类 switch (kind){ case 'pig': pet=new Pig(); break; default: pet=new Bird(); } //验证接口 Interface.ensureImplement(pet,Pet);//判断pet对象是否全部实行接口Pet里面全部的方法 pet.eat(); pet.register(); return pet; };(8) 使用,实质是子类对父类的实例化
这里实现其中一个宠物店,另外一个同理。
//子类对父类的实例化 var jim=new oneShop(); var pig= jim.getpet("dog"); pig.run(); pig.sing()(9)上述代码综合在一起为,代码如下
(function () { //(2)接口调用 var Pet=new Interface("Pet",["eat","run","sing","register"]); //(1)基类 分析后有共同的提出来作为基类 function basePet() { this.register=function () { document.write("宠物登记。。。。<br>"); }; this.eat=function () { document.write("宠物吃饭。。。。<br>"); } } //(3)实现类 继承基类+接口实现 function Dog() { Dog.superClass.constructor.call(this);//继承父类 //实现接口 this.run=function () { document.write("小狗跑......<br>") } this.sing=function () { document.write("小狗唱歌......<br>") } } function Cat() { Cat.superClass.constructor.call(this);//继承父类 //实现接口 this.run=function () { document.write("小猫跑......<br>") } this.sing=function () { document.write("小猫唱歌......<br>") } } function Pig() { Pig.superClass.constructor.call(this);//继承父类 //实现接口 this.run=function () { document.write("小猪跑......<br>") } this.sing=function () { document.write("小猪唱歌......<br>") } } function Bird() { Bird.superClass.constructor.call(this);//继承父类 //实现接口 this.run=function () { document.write("小鸟跑......<br>") }; this.sing=function () { document.write("小鸟唱歌......<br>") } } //继承 extend(Dog,basePet);//宠物的继承 extend(Cat,basePet); extend(Pig,basePet); extend(Bird,basePet); //(4)把核心商店抽取出来 var petShop=function () {}; petShop.prototype={//模拟抽象类 需要被子类覆盖 getPet:function (kind){ var pet=this.getpet(kind); pet.eat(); pet.register(); return pet; }, getpet:function (model){ throw new Error("该类是抽象类,不能实例化") } }; //(5)商店1 利用子类来满足之前的需求(多态) var oneShop=function () { } extend(oneShop,petShop);//继承 //覆写方法 oneShop.prototype.getpet=function (model) { //宠物对象 var pet; //宠物种类 switch (model){ case 'dog': pet=new Dog(); break; default: pet=new Bird(); } //验证接口 Interface.ensureImplement(pet,Pet);//判断pet对象是否全部实行接口Pet里面全部的方法 pet.eat(); pet.register(); return pet; }; //(5)商店2 twoShop=function () {}; extend(twoShop,petShop);//商店的继承 //覆写方法 twoShop.prototype.getPet=function (model) { //宠物对象 var pet; //宠物种类 switch (kind){ case 'pig': pet=new Pig(); break; default: pet=new Bird(); } //验证接口 Interface.ensureImplement(pet,Pet);//判断pet对象是否全部实行接口Pet里面全部的方法 pet.eat(); pet.register(); return pet; }; //(6)使用 子类对父类的实例化 var jim=new oneShop();//开宠物店 var pig= jim.getpet("dog");//从宠物店得到宠物 pig.run();//宠物功能 pig.sing()})();注:代码中的注释编号表示其大概思考过程及实现顺序。
总结一下,在该个模式中主要体现在多态多一点。现在我们将前面的各种综合在一起使用JavaScript的eval()做一个智能化的工厂。
4,通过eval()实现智能化工厂
(1)接口文件和继承文件的引入,如上述的一模一样,这里将不再重复贴代码了,直接开始我们的新东西吧。
(2)接口调用
var Pet=new Interface("Pet",["eat","run","sing","register"]);(3)将相同部分提取出来(简单的提取)
//基类 分析后有共同的提出来作为基类 function basePet() { this.register=function () { document.write("宠物登记。。。。<br>"); }; this.eat=function () { document.write("宠物吃饭。。。。<br>"); } }(4)各动物类
//实现类 继承基类+接口实现 function Dog() { Dog.superClass.constructor.call(this);//继承父类 //实现接口 this.run=function () { document.write("小狗跑......<br>") } this.sing=function () { document.write("小狗唱歌......<br>") } } function Cat() { Cat.superClass.constructor.call(this);//继承父类 //实现接口 this.run=function () { document.write("小猫跑......<br>") } this.sing=function () { document.write("小猫唱歌......<br>") } } function Pig() { Pig.superClass.constructor.call(this);//继承父类 //实现接口 this.run=function () { document.write("小猪跑......<br>") } this.sing=function () { document.write("小猪唱歌......<br>") } } function Bird() { Bird.superClass.constructor.call(this);//继承父类 //实现接口 this.run=function () { document.write("小鸟跑......<br>") }; this.sing=function () { document.write("小鸟唱歌......<br>") } }(5)实现各动物类继承基类
//继承 extend(Dog,basePet); extend(Cat,basePet); extend(Pig,basePet); extend(Bird,basePet);(6)将商店核心抽取出来,做成一个抽象类,代码如下,
var petShop=function () {}; petShop.prototype={//模拟抽象类 需要被子类覆盖 getPet:function (kind){ var pet=this.getpet(kind); pet.eat(); pet.register(); return pet; }, getpet:function (model){ throw new Error("该类是抽象类,不能实例化") } };(7)做一个智能工厂
//(5)智能工厂 只负责生成宠物 var PetFactory={ sellPet:function (kind) { var pet; pet=eval("new "+kind+"()"); Interface.ensureImplement(pet,Pet);//判断pet对象是否全部实行接口Pet里面全部的方法 return pet; } }(8)利用子类来满足各个商家的不同类型宠物店的实现 ,代码如下
其中一个子类
//利用子类来满足各个商家的不同类型宠物店的实现 (多态) var oneShop=function () { }; extend(oneShop,petShop);//继承 //覆写方法 oneShop.prototype.getpet=function (model) { //宠物对象 var pet=null; //宠物种类 var pets=["Dog","Cat","Bird"];//商店自己拥有的宠物 宠物货架 for(v in pets){//循环出索引 if(pets[v]==model){//model是我们自己传递过来需要创建的宠物 pet=PetFactory.sellPet(model); //验证接口 Interface.ensureImplement(pet,Pet);//判断pet对象是否全部实行接口Pet里面全部的方法 pet.eat(); pet.register(); break; } } return pet;另一个子类
//(商店2)利用子类来满足各个商家的不同类型宠物店的实现 (多态) twoShop=function () {}; extend(twoShop,petShop);//商店的继承 //覆写方法 twoShop.prototype.getPet=function (model) { //宠物对象 var pet=null; //宠物种类 var pets=["Pig"];//商店自己拥有的宠物 for(v in pets){//循环出索引 if(pets[v]==model){ pet=PetFactory.sellPet(model); //验证接口 Interface.ensureImplement(pet,Pet);//判断pet对象是否全部实行接口Pet里面全部的方法 pet.eat(); pet.register(); break; } } return pet; };(9)实现开宠物店卖宠物
这里我们来开第二个商店,卖Pig
var shop=new twoShop();//创建商店 var pet=shop.getPet("Pig");//从商店中得到宠物 pet.run();//宠物的功能(10)智能化工厂的代码
(function () { //(1)接口调用 var Pet=new Interface("Pet",["eat","run","sing","register"]); //(2)基类 分析后有共同的提出来作为基类 function basePet() { this.register=function () { document.write("宠物登记。。。。<br>"); }; this.eat=function () { document.write("宠物吃饭。。。。<br>"); } } //(3)各个动物类(实现类) 继承基类+接口实现 function Dog() { Dog.superClass.constructor.call(this);//继承父类 //实现接口 this.run=function () { document.write("小狗跑......<br>") } this.sing=function () { document.write("小狗唱歌......<br>") } } function Cat() { Cat.superClass.constructor.call(this);//继承父类 //实现接口 this.run=function () { document.write("小猫跑......<br>") } this.sing=function () { document.write("小猫唱歌......<br>") } } function Pig() { Pig.superClass.constructor.call(this);//继承父类 //实现接口 this.run=function () { document.write("小猪跑......<br>") } this.sing=function () { document.write("小猪唱歌......<br>") } } function Bird() { Bird.superClass.constructor.call(this);//继承父类 //实现接口 this.run=function () { document.write("小鸟跑......<br>") }; this.sing=function () { document.write("小鸟唱歌......<br>") } } //继承 extend(Dog,basePet); extend(Cat,basePet); extend(Pig,basePet); extend(Bird,basePet); //(4)把核心商店抽取出来 var petShop=function () {}; petShop.prototype={//模拟抽象类 需要被子类覆盖 getPet:function (kind){ var pet=this.getpet(kind); pet.eat(); pet.register(); return pet; }, getpet:function (model){ throw new Error("该类是抽象类,不能实例化") } }; //(5)智能工厂 只负责生成宠物 var PetFactory={ sellPet:function (kind) { var pet; pet=eval("new "+kind+"()"); Interface.ensureImplement(pet,Pet);//判断pet对象是否全部实行接口Pet里面全部的方法 return pet; } } //(6)(商店1)利用子类来满足各个商家的不同类型宠物店的实现 (多态) var oneShop=function () { }; extend(oneShop,petShop);//继承 //覆写方法 oneShop.prototype.getpet=function (model) { //宠物对象 var pet=null; //宠物种类 var pets=["Dog","Cat","Bird"];//商店自己拥有的宠物 宠物货架 for(v in pets){//循环出索引 if(pets[v]==model){//model是我们自己传递过来需要创建的宠物 pet=PetFactory.sellPet(model); //验证接口 Interface.ensureImplement(pet,Pet);//判断pet对象是否全部实行接口Pet里面全部的方法 pet.eat(); pet.register(); break; } } return pet; }; //(商店2)利用子类来满足各个商家的不同类型宠物店的实现 (多态) twoShop=function () {}; extend(twoShop,petShop);//商店的继承 //覆写方法 twoShop.prototype.getPet=function (model) { //宠物对象 var pet=null; //宠物种类 var pets=["Pig"];//商店自己拥有的宠物 for(v in pets){//循环出索引 if(pets[v]==model){ pet=PetFactory.sellPet(model); //验证接口 Interface.ensureImplement(pet,Pet);//判断pet对象是否全部实行接口Pet里面全部的方法 pet.eat(); pet.register(); break; } } return pet; };//(7)开宠物店卖宠物 var shop=new twoShop(); var pet=shop.getPet("Pig"); pet.run();})();总结一下,该种智能化工厂的特点体现在我们需要什么宠物店时,我们可以直接通过智能化工厂创建。很完美。
1.需要根据不同参数产生不同实例,这些实例有一些共性的场景
2.使用者只需要使用产品,不需要知道产品的创建细节
注意:除非是适用场景,否则不可滥用工厂模式,会造成代码的复杂度。
1.工厂类集中了所有对象的创建,便于对象创建的统一管理
2.对象的使用者仅仅是使用产品,实现了单一职责
3.便于扩展,如果新增了一种业务,只需要增加相关的业务对象类和工厂类中的生产业务对象的方法,不需要修改其他的地方。
感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun测试上述代码运行效果。
更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》
希望本文所述对大家JavaScript程序设计有所帮助。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
本文实例讲述了javascript设计模式–工厂模式原理与应用。分享给大家供大家参考,具体如下:介绍:前面我们介绍了简单工厂模式,简单工厂模式存在一个严重的问题
本文实例讲述了javascript设计模式–抽象工厂模式原理与应用。分享给大家供大家参考,具体如下:介绍:基于工厂模式,继续升级。来解决工厂模式存在多个工厂类的
本文实例讲述了javascript设计模式–简单工厂模式。分享给大家供大家参考,具体如下:介绍:简单工厂模式是最常用的一类创建型设计模式。其中简单工厂模式并不属
本文主要内容参考来自JavaScript高级程序设计,面向对象与原型章节:1、工厂模式ECMAScript可以通过工厂模式来创建对象://工厂模式functio
本文实例讲述了Python设计模式之简单工厂模式。分享给大家供大家参考,具体如下:简单工厂模式(SimpleFactoryPattern):是通过专门定义一个类