JavaScript设计模式:简单工厂、复杂工厂与智能工厂详解

作者:闭包旅人

时间:2026-10-23

浏览:460

本文深入解析JavaScript中的工厂模式,涵盖简单工厂、复杂工厂及基于eval的智能工厂三种实现。通过宠物店案例演示如何解耦对象创建与使用,结合接口定义与继承机制,帮助开发者掌握多态应用与代码扩展技巧,避免滥用导致的复杂度问题。

文章目录

本文详细阐述了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)定义一个宠物店类,并在其原型上进行扩展。


 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. 便于扩展,如果新增了一种业务,只需要增加相关的业务对象类和工厂类中的生产业务对象的方法,不需要修改其他的地方。

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.jb51.net/code/HtmlJsRun测试上述代码运行效果。

更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》。

希望本文所述对大家JavaScript程序设计有所帮助。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章