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 相关文章推荐
javascript中onmouse事件在div中失效问题的解决方法
Jan 09 Javascript
window.open不被拦截的实现代码
Aug 22 Javascript
jquery 多行文本框(textarea)高度变化
Jul 03 Javascript
JQuery的Ajax请求实现局部刷新的简单实例
Feb 11 Javascript
jQuery 文本框得失焦点的简单实例
Feb 19 Javascript
Node.js使用Express.Router的方法
Nov 14 Javascript
node基于puppeteer模拟登录抓取页面的实现
May 09 Javascript
vue如何解决循环引用组件报错的问题
Sep 22 Javascript
jQuery AJAX与jQuery事件的分析讲解
Feb 18 jQuery
微信小程序(订阅消息)功能
Oct 25 Javascript
JS中数组实现代码(倒序遍历数组,数组连接字符串)
Dec 29 Javascript
JavaScript canvas绘制圆弧与圆形
Feb 18 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
综合图片计数器
2006/10/09 PHP
PHP备份数据库生成SQL文件并下载的函数代码
2012/02/05 PHP
php Ubb代码编辑器函数代码
2012/07/05 PHP
Yii2中YiiBase自动加载类、引用文件方法分析(autoload)
2016/07/25 PHP
Laravel构建即时应用的一种实现方法详解
2017/08/31 PHP
Gambit vs CL BO3 第一场 2.13
2021/03/10 DOTA
又一个图片自动缩小的JS代码
2007/03/10 Javascript
ie和firefox不兼容的解决方法集合
2009/04/28 Javascript
你必须知道的Javascript知识点之&quot;字面量和对应类型&quot;说明介绍
2013/04/23 Javascript
基于jquery实现控制经纬度显示地图与卫星
2013/05/20 Javascript
jQuery基于当前元素进行下一步的遍历
2014/05/20 Javascript
php结合imgareaselect实现图片裁剪
2015/07/05 Javascript
一个简单不报错的summernote 图片上传案例
2016/07/11 Javascript
AngularJS 中使用Swiper制作滚动图不能滑动的解决方法
2016/11/15 Javascript
微信小程序  TLS 版本必须大于等于1.2问题解决
2017/02/22 Javascript
vue 将页面公用的头部组件化的方法
2017/12/18 Javascript
NodeJS实现不可逆加密与密码密文保存的方法
2018/03/16 NodeJs
微信小程序实现的自定义分享功能示例
2019/02/12 Javascript
5分钟教你用nodeJS手写一个mock数据服务器的方法
2019/09/10 NodeJs
[46:00]DOTA2上海特级锦标赛主赛事日 - 2 胜者组第一轮#4EG VS Fnatic第一局
2016/03/03 DOTA
python登录QQ邮箱发信的实现代码
2013/02/10 Python
Python爬虫辅助利器PyQuery模块的安装使用攻略
2016/04/24 Python
Python读取和处理文件后缀为.sqlite的数据文件(实例讲解)
2017/06/27 Python
利用Pandas 创建空的DataFrame方法
2018/04/08 Python
Python之修改图片像素值的方法
2019/07/03 Python
Python 使用 environs 库定义环境变量的方法
2020/02/25 Python
keras 获取某层输出 获取复用层的多次输出实例
2020/05/23 Python
canvas粒子动画背景的实现示例
2018/09/03 HTML / CSS
微信小程序“圣诞帽”的实现思路详解
2017/12/28 HTML / CSS
Canon佳能美国官方商店:购买数码相机、数码单反相机、镜头和打印机
2016/11/15 全球购物
员工晚婚的请假条
2014/02/08 职场文书
班组长竞聘书
2014/03/31 职场文书
老兵退伍标语
2014/10/07 职场文书
天鹅湖观后感
2015/06/09 职场文书
致创业您:正能量激励人心句子(48条)
2019/08/15 职场文书
vue项目proxyTable配置和部署服务器
2022/04/14 Vue.js