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 相关文章推荐
提取字符串中年月日的函数代码
Nov 05 Javascript
动态加载JS文件的三种方法
Nov 08 Javascript
jquery取消选择select下拉框示例代码
Feb 22 Javascript
js弹出确认是否删除对话框
Mar 27 Javascript
js+HTML5基于过滤器从摄像头中捕获视频的方法
Jun 16 Javascript
去除html代码里面的script正则方法
May 19 Javascript
一步一步封装自己的HtmlHelper组件BootstrapHelper(二)
Sep 14 Javascript
AngularJS实现根据变量改变动态加载模板的方法
Nov 04 Javascript
JS给按钮添加跳转功能类似a标签
May 30 Javascript
vue移动端轻量级的轮播组件实现代码
Jul 12 Javascript
详解js的视频和音频采集
Aug 09 Javascript
小程序最新获取用户昵称和头像的方法总结
Sep 23 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
PHPWind 发帖回帖Api PHP版打包下载
2010/02/08 PHP
php重定向的三种方法分享
2012/02/22 PHP
通过php删除xml文档内容的方法
2015/01/23 PHP
PHP环形链表实现方法示例
2017/09/15 PHP
PHP如何获取Cookie并实现模拟登录
2020/07/16 PHP
Add a Picture to a Microsoft Word Document
2007/06/15 Javascript
javascript动态加载二
2012/08/22 Javascript
jQuery 仿百度输入标签插件附效果图
2014/07/04 Javascript
借助JavaScript脚本判断浏览器Flash Player信息的方法
2014/07/09 Javascript
jQuery ajax请求返回list数据动态生成input标签,并把list数据赋值到input标签
2016/03/29 Javascript
jQuery获取单选按钮radio选中值与去除所有radio选中状态的方法
2017/05/20 jQuery
基于jquery日历价格、库存等设置插件
2020/07/05 jQuery
js实现方块上下左右移动效果
2017/08/17 Javascript
利用babel将es6语法转es5的简单示例
2017/12/01 Javascript
JavaScript+H5实现微信摇一摇功能
2018/05/23 Javascript
angularjs自定义过滤器demo示例
2019/08/24 Javascript
初学vue出现空格警告的原因及其解决方案
2019/10/31 Javascript
微信小程序转化为uni-app项目的方法示例
2020/05/22 Javascript
[02:27]DOTA2英雄基础教程 莱恩
2014/01/17 DOTA
python判断字符串是否纯数字的方法
2014/11/19 Python
黑科技 Python脚本帮你找出微信上删除你好友的人
2016/01/07 Python
python利用dir函数查看类中所有成员函数示例代码
2017/09/08 Python
python 读写excel文件操作示例【附源码下载】
2019/06/19 Python
解决Mac下使用python的坑
2019/08/13 Python
Python 实现OpenCV格式和PIL.Image格式互转
2020/01/09 Python
对python中 math模块下 atan 和 atan2的区别详解
2020/01/17 Python
Python获取浏览器窗口句柄过程解析
2020/07/25 Python
在 Python 中使用 MQTT的方法
2020/08/18 Python
naturalizer加拿大官网:美国娜然女鞋
2017/04/04 全球购物
法雷奥SQA(electric)面试问题
2016/01/23 面试题
操行评语大全
2014/04/30 职场文书
法定代表人身份证明书
2014/09/10 职场文书
工作调动申请报告
2015/05/18 职场文书
承兑汇票延期证明
2015/06/23 职场文书
获奖感言范文
2015/07/31 职场文书
css3带你实现3D转换效果
2022/02/24 HTML / CSS