JavaScript設計模式--簡單工廠模式定義與應用案例詳解
本文實例講述了JavaScript設計模式--簡單工廠模式定義與應用。分享給大家供大家參考,具體如下:
一,介紹
工廠模式創(chuàng)建對象(視為工廠里的產(chǎn)品)時無需指定創(chuàng)建對象的具體類。
工廠模式定義一個用于創(chuàng)建對象的接口,這個接口由子類決定實例化哪一個類。該模式使一個類的實例化延遲到了子類。而子類可以重寫接口方法以便創(chuàng)建的時候指定自己的對象類型。
在這里將工廠簡單分為三種:
(1)簡單工廠:通過第三方的類完成松耦合的任務。
(2)復雜工廠:通過把實例化的任務交給子類來完成的,用以到達松耦合的目的。
(3)超級工廠:通過eval()來完成智能工廠。
工廠的目的:在于判斷接口最終用哪個類實例化(故與接口密不可分)。
使用工廠最終達到的效果是:多態(tài),和類與類之間的松耦合。
二,正文部分
工廠模式與接口是密不可分的所以我們需要先引入接口文件和繼承類文件
(1)接口文件:
//定義一個靜態(tài)方法來實現(xiàn)接口與實現(xiàn)類的直接檢驗
//靜態(tài)方法不要寫出Interface.prototype ,因為這是寫到接口的原型鏈上的
//我們要把靜態(tài)的函數(shù)直接寫到類層次上
//(1)定義一個接口類
var Interface=function (name,methods) {//name:接口名字
if(arguments.length<2){
alert("必須是兩個參數(shù)")
}
this.name=name;
this.methods=[];//定義一個空數(shù)組裝載函數(shù)名
for(var i=0;i<methods.length;i++){
if(typeof methods[i]!="string"){
alert("函數(shù)名必須是字符串類型");
}else {
this.methods.push( methods[i]);
}
}
};
Interface.ensureImplement=function (object) {
if(arguments.length<2){
throw new Error("參數(shù)必須不少于2個")
return false;
}
for(var i=1;i<arguments.length;i++){
var inter=arguments[i];
//如果是接口就必須是Interface類型
if(inter.constructor!=Interface){
throw new Error("如果是接口類的話,就必須是Interface類型");
}
//判斷接口中的方法是否全部實現(xiàn)
//遍歷函數(shù)集合
for(var j=0;j<inter.methods.length;j++){
var method=inter.methods[j];//接口中所有函數(shù)
//object[method]傳入的函數(shù)
//最終是判斷傳入的函數(shù)是否與接口中所用函數(shù)匹配
if(!object[method]||typeof object[method]!="function" ){//實現(xiàn)類中必須有方法名字與接口中所用方法名相同
throw new Error("實現(xiàn)類中沒有完全實現(xiàn)接口中的所有方法")
}
}
}
}
(2)繼承文件
/*創(chuàng)建extend函數(shù)為了程序中所有的繼承操作*/
//subClass:子類 superClass:超類
function extend(subClass,superClass) {
//1,使子類原型屬性等于父類的原型屬性
//初始化一個中間空對象,目的是為了轉(zhuǎn)換主父關系
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)那么也要把你的構(gòu)造函數(shù)級別降下來
if (superClass.prototype.constructor == Object.prototype.constructor) {
superClass.prototype.constructor = superClass;
}
}
通過下面的例子,逐步引進工廠模式及改進工廠模式
1,工廠模式的引入,
(1)創(chuàng)建接口對象
var Pet=new Interface("Pet",["eat","run","sing","register"]);
(2)定義一個寵物店類并在prototype上進行擴展
var PetShop=function () {}
PetShop.prototype={
//出售寵物的方法
sellPet: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對象是否全部實現(xiàn)接口Pet里面全部的方法 (對象,接口)
pet.eat();
pet.register();
return pet;
}
}
(3)分析寵物的一些特點可以將一些公共的部分提取出來(這里只是簡單的提?。?/p>
//基類 有共同的提出來
function basePet() {
this.register=function () {
document.write("寵物登記...<br>");
}
this.eat=function () {
document.write("寵物吃飯...<br>");
}
}
(4)各個實現(xiàn)類 ---這里是各種動物
function Dog() {
Dog.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口部分
this.run=function () {
document.write("小狗跑......<br>")
}
this.sing=function () {
document.write("小狗唱歌......<br>")
}
}
function Cat() {
Cat.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口部分
this.run=function () {
document.write("小貓跑......<br>")
}
this.sing=function () {
document.write("小貓唱歌......<br>")
}
}
function Pig() {
Pig.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口部分
this.run=function () {
document.write("小豬跑......<br>")
}
this.sing=function () {
document.write("小豬唱歌......<br>")
}
}
function Bird() {
Bird.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口部分
this.run=function () {
document.write("小鳥跑......<br>")
}
this.sing=function () {
document.write("小鳥唱歌......<br>")
}
}
(5)各個實現(xiàn)類繼承基類
//繼承
extend(Dog,basePet); extend(Cat,basePet); extend(Pig,basePet); extend(Bird,basePet);
(6)創(chuàng)建寵物的開始賣寵物
var newPetShop=new PetShop();
var flowerPig=newPetShop.sellPet("pig");
flowerPig.run();
結(jié)果為:

總結(jié)一下,上述好像沒怎么體現(xiàn)有關工廠之類的,我們應該注意到這么一個問題就是:當需要增加一個新品種寵物時,我們需要修改 '寵物店類',耦合度較高。
為了解決這個問題我們使用簡單工廠模式來解決。
2,簡單工廠模式(針對上述的改進)
(1)接口文件與繼承文件的的引入 同上面
(2)靜態(tài)工廠
//使用工廠方式創(chuàng)建寵物對象
// 靜態(tài)工廠
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)利用工廠創(chuàng)建寵物店對象
var factoryPetShop=function () {}
factoryPetShop.prototype={
getPet:function (kind) {
var pet=factoryPet.getPet(kind);
pet.eat();
pet.register();
return pet;
}
}
(4)從寵物店購買寵物實現(xiàn)
var newPetShop=new factoryPetShop();
var flowerCat=newPetShop.getPet("cat");
flowerCat.sing();
(5)使用簡單工廠實現(xiàn)的全部代碼(數(shù)字標號表示其思考的先后順序)
(function () {
//(2)接口調(diào)用
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)實現(xiàn)類 繼承基類+接口實現(xiàn)
function Dog() {
Dog.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口
this.run=function () {
document.write("小狗跑......<br>")
}
this.sing=function () {
document.write("小狗唱歌......<br>")
}
}
function Cat() {
Cat.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口
this.run=function () {
document.write("小貓跑......<br>")
}
this.sing=function () {
document.write("小貓唱歌......<br>")
}
}
function Pig() {
Pig.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口
this.run=function () {
document.write("小豬跑......<br>")
}
this.sing=function () {
document.write("小豬唱歌......<br>")
}
}
function Bird() {
Bird.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口
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)使用工廠方式創(chuàng)建寵物對象
// 靜態(tài)工廠
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();
})()
總結(jié)一下,上述看似完美,但是任有問題存在:比如說:張三的寵物店想賣哈士奇,李四的寵物店想賣鳥時,這樣的話,寵物都是通過一個工廠生產(chǎn)的,并不一定滿足各個賣家的需求。
所以我們需要根據(jù)各個廠家的需求,有不同的工廠,各個賣家可以根據(jù)自己需求使用不同的工廠(其實是利用不同子類實現(xiàn)各自合適的工廠),用于滿足每個寵物店的不同。
于是我們有了復雜的工廠用來解決該問題。
3,復雜工廠:通過把實例化的任務交給子類來完成的,用以到達松耦合的目的。
此處同樣是根據(jù)上述進行改進的,還是簡單的說明一下實現(xiàn)過程
(1)在html中將接口文件的引進,代碼為
//定義一個靜態(tài)方法來實現(xiàn)接口與實現(xiàn)類的直接檢驗
//靜態(tài)方法不要寫出Interface.prototype ,因為這是寫到接口的原型鏈上的
//我們要把靜態(tài)的函數(shù)直接寫到類層次上
//定義一個接口類
var Interface=function (name,methods) {//name:接口名字
if(arguments.length<2){
alert("必須是兩個參數(shù)")
}
this.name=name;
this.methods=[];//定義一個空數(shù)組裝載函數(shù)名
for(var i=0;i<methods.length;i++){
if(typeof methods[i]!="string"){
alert("函數(shù)名必須是字符串類型");
}else {
this.methods.push( methods[i]);
}
}
};
Interface.ensureImplement=function (object) {
if(arguments.length<2){
throw new Error("參數(shù)必須不少于2個")
return false;
}
for(var i=1;i<arguments.length;i++){
var inter=arguments[i];
//如果是接口就必須是Interface類型
if(inter.constructor!=Interface){
throw new Error("如果是接口類的話,就必須是Interface類型");
}
//判斷接口中的方法是否全部實現(xiàn)
//遍歷函數(shù)集合
for(var j=0;j<inter.methods.length;j++){
var method=inter.methods[j];//接口中所有函數(shù)
//object[method]傳入的函數(shù)
//最終是判斷傳入的函數(shù)是否與接口中所用函數(shù)匹配
if(!object[method]||typeof object[method]!="function" ){//實現(xiàn)類中必須有方法名字與接口中所用方法名相同
throw new Error("實現(xiàn)類中沒有完全實現(xiàn)接口中的所有方法")
}
}
}
}
(2)在html中將繼承文件引入,代碼如下,
/*創(chuàng)建extend函數(shù)為了程序中所有的繼承操作*/
//subClass:子類 superClass:超類
function extend(subClass,superClass) {
//1,使子類原型屬性等于父類的原型屬性
//初始化一個中間空對象,目的是為了轉(zhuǎn)換主父關系
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)那么也要把你的構(gòu)造函數(shù)級別降下來
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)各個具體的實現(xiàn)類:繼承基類+接口實現(xiàn)
//各個寵物類(實現(xiàn)類) 繼承基類+接口實現(xiàn)
function Dog() {
Dog.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口
this.run=function () {
document.write("小狗跑......<br>")
}
this.sing=function () {
document.write("小狗唱歌......<br>")
}
}
function Cat() {
Cat.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口
this.run=function () {
document.write("小貓跑......<br>")
}
this.sing=function () {
document.write("小貓唱歌......<br>")
}
}
function Pig() {
Pig.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口
this.run=function () {
document.write("小豬跑......<br>")
}
this.sing=function () {
document.write("小豬唱歌......<br>")
}
}
function Bird() {
Bird.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口
this.run=function () {
document.write("小鳥跑......<br>")
};
this.sing=function () {
document.write("小鳥唱歌......<br>")
}
}
(5)實現(xiàn)類與基類的繼承實現(xiàn),代碼如下(調(diào)用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)利用子類來滿足各個商家的不同類型寵物店的實現(xiàn) ,代碼如下
//利用子類來滿足之前的需求(多態(tài))
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) 使用,實質(zhì)是子類對父類的實例化
這里實現(xiàn)其中一個寵物店,另外一個同理。
//子類對父類的實例化
var jim=new oneShop();
var pig= jim.getpet("dog");
pig.run();
pig.sing()
(9)上述代碼綜合在一起為,代碼如下
(function () {
//(2)接口調(diào)用
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)實現(xiàn)類 繼承基類+接口實現(xiàn)
function Dog() {
Dog.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口
this.run=function () {
document.write("小狗跑......<br>")
}
this.sing=function () {
document.write("小狗唱歌......<br>")
}
}
function Cat() {
Cat.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口
this.run=function () {
document.write("小貓跑......<br>")
}
this.sing=function () {
document.write("小貓唱歌......<br>")
}
}
function Pig() {
Pig.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口
this.run=function () {
document.write("小豬跑......<br>")
}
this.sing=function () {
document.write("小豬唱歌......<br>")
}
}
function Bird() {
Bird.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口
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 利用子類來滿足之前的需求(多態(tài))
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()
})();
注:代碼中的注釋編號表示其大概思考過程及實現(xiàn)順序。
總結(jié)一下,在該個模式中主要體現(xiàn)在多態(tài)多一點?,F(xiàn)在我們將前面的各種綜合在一起使用JavaScript的eval()做一個智能化的工廠。
4,通過eval()實現(xiàn)智能化工廠
(1)接口文件和繼承文件的引入,如上述的一模一樣,這里將不再重復貼代碼了,直接開始我們的新東西吧。
(2)接口調(diào)用
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)各動物類
//實現(xiàn)類 繼承基類+接口實現(xiàn)
function Dog() {
Dog.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口
this.run=function () {
document.write("小狗跑......<br>")
}
this.sing=function () {
document.write("小狗唱歌......<br>")
}
}
function Cat() {
Cat.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口
this.run=function () {
document.write("小貓跑......<br>")
}
this.sing=function () {
document.write("小貓唱歌......<br>")
}
}
function Pig() {
Pig.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口
this.run=function () {
document.write("小豬跑......<br>")
}
this.sing=function () {
document.write("小豬唱歌......<br>")
}
}
function Bird() {
Bird.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口
this.run=function () {
document.write("小鳥跑......<br>")
};
this.sing=function () {
document.write("小鳥唱歌......<br>")
}
}
(5)實現(xiàn)各動物類繼承基類
//繼承 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("該類是抽象類,不能實例化")
}
};
//這里是做成抽象類其中的getpet方法是通過子類實現(xiàn)的。
(7)做一個智能工廠
//(5)智能工廠 只負責生成寵物
var PetFactory={
sellPet:function (kind) {
var pet;
pet=eval("new "+kind+"()");
Interface.ensureImplement(pet,Pet);//判斷pet對象是否全部實行接口Pet里面全部的方法
return pet;
}
}
(8)利用子類來滿足各個商家的不同類型寵物店的實現(xiàn) ,代碼如下
其中一個子類
//利用子類來滿足各個商家的不同類型寵物店的實現(xiàn) (多態(tài))
var oneShop=function () { };
extend(oneShop,petShop);//繼承
//覆寫方法
oneShop.prototype.getpet=function (model) {
//寵物對象
var pet=null;
//寵物種類
var pets=["Dog","Cat","Bird"];//商店自己擁有的寵物 寵物貨架
for(v in pets){//循環(huán)出索引
if(pets[v]==model){//model是我們自己傳遞過來需要創(chuàng)建的寵物
pet=PetFactory.sellPet(model);
//驗證接口
Interface.ensureImplement(pet,Pet);//判斷pet對象是否全部實行接口Pet里面全部的方法
pet.eat();
pet.register();
break;
}
}
return pet;
另一個子類
//(商店2)利用子類來滿足各個商家的不同類型寵物店的實現(xiàn) (多態(tài))
twoShop=function () {};
extend(twoShop,petShop);//商店的繼承
//覆寫方法
twoShop.prototype.getPet=function (model) {
//寵物對象
var pet=null;
//寵物種類
var pets=["Pig"];//商店自己擁有的寵物
for(v in pets){//循環(huán)出索引
if(pets[v]==model){
pet=PetFactory.sellPet(model);
//驗證接口
Interface.ensureImplement(pet,Pet);//判斷pet對象是否全部實行接口Pet里面全部的方法
pet.eat();
pet.register();
break;
}
}
return pet;
};
(9)實現(xiàn)開寵物店賣寵物
這里我們來開第二個商店,賣Pig
var shop=new twoShop();//創(chuàng)建商店
var pet=shop.getPet("Pig");//從商店中得到寵物
pet.run();//寵物的功能
(10)智能化工廠的代碼
(function () {
//(1)接口調(diào)用
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)各個動物類(實現(xiàn)類) 繼承基類+接口實現(xiàn)
function Dog() {
Dog.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口
this.run=function () {
document.write("小狗跑......<br>")
}
this.sing=function () {
document.write("小狗唱歌......<br>")
}
}
function Cat() {
Cat.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口
this.run=function () {
document.write("小貓跑......<br>")
}
this.sing=function () {
document.write("小貓唱歌......<br>")
}
}
function Pig() {
Pig.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口
this.run=function () {
document.write("小豬跑......<br>")
}
this.sing=function () {
document.write("小豬唱歌......<br>")
}
}
function Bird() {
Bird.superClass.constructor.call(this);//繼承父類
//實現(xiàn)接口
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)利用子類來滿足各個商家的不同類型寵物店的實現(xiàn) (多態(tài))
var oneShop=function () { };
extend(oneShop,petShop);//繼承
//覆寫方法
oneShop.prototype.getpet=function (model) {
//寵物對象
var pet=null;
//寵物種類
var pets=["Dog","Cat","Bird"];//商店自己擁有的寵物 寵物貨架
for(v in pets){//循環(huán)出索引
if(pets[v]==model){//model是我們自己傳遞過來需要創(chuàng)建的寵物
pet=PetFactory.sellPet(model);
//驗證接口
Interface.ensureImplement(pet,Pet);//判斷pet對象是否全部實行接口Pet里面全部的方法
pet.eat();
pet.register();
break;
}
}
return pet;
};
//(商店2)利用子類來滿足各個商家的不同類型寵物店的實現(xiàn) (多態(tài))
twoShop=function () {};
extend(twoShop,petShop);//商店的繼承
//覆寫方法
twoShop.prototype.getPet=function (model) {
//寵物對象
var pet=null;
//寵物種類
var pets=["Pig"];//商店自己擁有的寵物
for(v in pets){//循環(huán)出索引
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();
})();
總結(jié)一下,該種智能化工廠的特點體現(xiàn)在我們需要什么寵物店時,我們可以直接通過智能化工廠創(chuàng)建。很完美。
3,工廠模式的使用場景
1.需要根據(jù)不同參數(shù)產(chǎn)生不同實例,這些實例有一些共性的場景
2.使用者只需要使用產(chǎn)品,不需要知道產(chǎn)品的創(chuàng)建細節(jié)
注意:除非是適用場景,否則不可濫用工廠模式,會造成代碼的復雜度。
4.簡單工廠模式優(yōu)點
1.工廠類集中了所有對象的創(chuàng)建,便于對象創(chuàng)建的統(tǒng)一管理
2.對象的使用者僅僅是使用產(chǎn)品,實現(xiàn)了單一職責
3.便于擴展,如果新增了一種業(yè)務,只需要增加相關的業(yè)務對象類和工廠類中的生產(chǎn)業(yè)務對象的方法,不需要修改其他的地方。
感興趣的朋友可以使用在線HTML/CSS/JavaScript代碼運行工具:http://tools.jb51.net/code/HtmlJsRun測試上述代碼運行效果。
更多關于JavaScript相關內(nèi)容感興趣的讀者可查看本站專題:《javascript面向?qū)ο笕腴T教程》、《JavaScript錯誤與調(diào)試技巧總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》及《JavaScript數(shù)學運算用法總結(jié)》
希望本文所述對大家JavaScript程序設計有所幫助。
相關文章
js實現(xiàn)控制文件拖拽并獲取拖拽內(nèi)容功能
本片文章主要給大家分享了用JS寫出控制文件拖拽并獲取拖拽內(nèi)容功能實現(xiàn)過程,以及代碼分享,有興趣的一起學習下。2018-02-02
瀏覽器環(huán)境下JavaScript腳本加載與執(zhí)行探析之動態(tài)腳本與Ajax腳本注入
這篇文章主要介紹了瀏覽器環(huán)境下JavaScript腳本加載與執(zhí)行探析之動態(tài)腳本與Ajax腳本注入 的相關資料,需要的朋友可以參考下2016-01-01

