JavaScript設計模式--簡單工廠模式


一,介紹

工廠模式創建對象(視為工廠里的產品)時無需指定創建對象的具體類。

工廠模式定義一個用於創建對象的接口,這個接口由子類決定實例化哪一個類。該模式使一個類的實例化延遲到了子類。而子類可以重寫接口方法以便創建的時候指定自己的對象類型。

在這里將工廠簡單分為三種:

(1)簡單工廠:通過第三方的類完成松耦合的任務。
(2)復雜工廠:通過把實例化的任務交給子類來完成的,用以到達松耦合的目的。
(3)超級工廠:通過eval()來完成智能工廠。
工廠的目的:
在於判斷接口最終用哪個類實例化(故與接口密不可分)。
使用工廠
最終達到的效果是:多態,和類與類之間的松耦合。

二,正文部分
工廠模式與接口是密不可分的所以我們需要先引入接口文件和繼承類文件
(1)接口文件:
//定義一個靜態方法來實現接口與實現類的直接檢驗
//靜態方法不要寫出Interface.prototype ,因為這是寫到接口的原型鏈上的
//我們要把靜態的函數直接寫到類層次上
//(1)定義一個接口類
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)繼承文件

/*創建extend函數為了程序中所有的繼承操作*/
//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)創建接口對象
  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對象是否全部實現接口Pet里面全部的方法    (對象,接口)
          pet.eat();
          pet.register();
          return pet;

        }
    }
(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 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中將繼承文件引入,代碼如下,

/*創建extend函數為了程序中所有的繼承操作*/
//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("該類是抽象類,不能實例化")

        }
    };
//這里是做成抽象類其中的getpet方法是通過子類實現的。

 

(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();

})();

總結一下,該種智能化工廠的特點體現在我們需要什么寵物店時,我們可以直接通過智能化工廠創建。很完美。

 

 3,工廠模式的使用場景

1.需要根據不同參數產生不同實例,這些實例有一些共性的場景
2.使用者只需要使用產品,不需要知道產品的創建細節

注意:除非是適用場景,否則不可濫用工廠模式,會造成代碼的復雜度。
4.簡單工廠模式優點

1.工廠類集中了所有對象的創建,便於對象創建的統一管理
2.對象的使用者僅僅是使用產品,實現了單一職責
3.便於擴展,如果新增了一種業務,只需要增加相關的業務對象類和工廠類中的生產業務對象的方法,不需要修改其他的地方。



 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM