JavaScript设计模式--简单工厂模式定义与应用案例详解


Posted in Javascript onMay 23, 2020

本文实例讲述了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();

结果为:

JavaScript设计模式--简单工厂模式定义与应用案例详解

总结一下,上述好像没怎么体现有关工厂之类的,我们应该注意到这么一个问题就是:当需要增加一个新品种宠物时,我们需要修改 '宠物店类',耦合度较高。

为了解决这个问题我们使用简单工厂模式来解决。

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.3water.com/code/HtmlJsRun测试上述代码运行效果。

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

Javascript 相关文章推荐
基于MVC3方式实现下拉列表联动(JQuery)
Sep 02 Javascript
window.onload与$(document).ready()的区别分析
May 30 Javascript
jQuery 1.9.1源码分析系列(十四)之常用jQuery工具
Dec 02 Javascript
JavaScript、tab切换完整版(自动切换、鼠标移入停止、移开运行)
Jan 05 Javascript
第三篇Bootstrap网格基础
Jun 21 Javascript
JS实现页面进入和返回定位到具体位置
Dec 08 Javascript
javascript实现多张图片左右无缝滚动效果
Mar 22 Javascript
bootstrap daterangepicker汉化以及扩展功能
Jun 15 Javascript
JavaScript数据结构与算法之队列原理与用法实例详解
Nov 22 Javascript
element-ui 限制日期选择的方法(datepicker)
May 16 Javascript
vue添加axios,并且指定baseurl的方法
Sep 19 Javascript
js实现鼠标拖拽缩放div实例代码
Mar 25 Javascript
基于element-ui封装可搜索的懒加载tree组件的实现
May 22 #Javascript
微信小程序点击滚动到指定位置的实现
May 22 #Javascript
使用JavaScript通过前端发送电子邮件
May 22 #Javascript
uni-app微信小程序登录授权的实现
May 22 #Javascript
jQuery 选择器用法实例分析【prev + next】
May 22 #jQuery
jQuery--遍历操作实例小结【后代、同胞及过滤】
May 22 #jQuery
uni-app使用微信小程序云函数的步骤示例
May 22 #Javascript
You might like
PHP4.04简明安装
2006/10/09 PHP
PHP调用.NET的WebService 简单实例
2015/03/27 PHP
php生成gif动画的方法
2015/11/05 PHP
CodeIgniter表单验证方法实例详解
2016/03/03 PHP
Laravel 5.3 学习笔记之 安装
2016/08/28 PHP
PHP实现用户登录的案例代码
2018/05/10 PHP
PHP实现redis限制单ip、单用户的访问次数功能示例
2018/06/16 PHP
PHP从尾到头打印链表实例讲解
2018/09/27 PHP
js设置function参数默认值(适合没有传参情况)
2014/02/24 Javascript
javascript + jquery实现定时修改文章标题
2014/03/19 Javascript
使用jQuery不判断浏览器高度解决iframe自适应高度问题
2014/12/16 Javascript
JQuery设置时间段下拉选择实例
2014/12/30 Javascript
Javascript实现计算个人所得税
2015/05/10 Javascript
JavaScript数组去重的3种方法和代码实例
2015/07/01 Javascript
基于jquery实现的树形菜单效果代码
2015/09/06 Javascript
JS实现不使用图片仿Windows右键菜单效果代码
2015/10/22 Javascript
JavaScript设置、获取、清除单值和多值cookie的方法
2015/11/17 Javascript
详解JavaScript逻辑Not运算符
2015/12/04 Javascript
用React-Native+Mobx做一个迷你水果商城APP(附源码)
2017/12/25 Javascript
JS实现横向轮播图(初级版)
2020/06/24 Javascript
js实现弹幕飞机效果
2020/08/27 Javascript
详解JavaScript执行模型
2020/11/16 Javascript
原生JavaScript实现随机点名表
2021/01/14 Javascript
python ddt实现数据驱动
2018/03/14 Python
windows下 兼容Python2和Python3的解决方法
2018/12/05 Python
python 随机打乱 图片和对应的标签方法
2018/12/14 Python
在Python中字典根据多项规则排序的方法
2019/01/21 Python
Python 微信爬虫完整实例【单线程与多线程】
2019/07/06 Python
Python 生成VOC格式的标签实例
2020/03/10 Python
网络安全类面试题
2015/08/01 面试题
超市促销实习自我鉴定
2013/09/23 职场文书
教师自我评价范例
2013/09/24 职场文书
建筑工程技术应届生求职信
2013/11/17 职场文书
商务邀请函范文
2014/01/14 职场文书
《夹竹桃》教学反思
2014/04/20 职场文书
2015年语文教学工作总结
2015/05/25 职场文书