首页 > 代码库 > 工厂模式一之简单工厂

工厂模式一之简单工厂

工厂用来生产商品,然后卖给供应商,再由供应商转手给门店,再卖给顾客 。这样的一种生产到供应的过程,看看如何应用到我们的程序中。

1.下面以衣服店为例子。

第一步 

clothes.js

//创建一个衣服店模型。var ClothesShop = function (){}ClothesShop.prototype = {    sellClothes: function (color){        var clothesType = [‘Red‘, ‘Blue‘, ‘Yello‘, ‘Green‘, ‘Gray‘];        var clothes;        for(var i = 0, len = clothesType.length; i < len; i++) {            if(color === clothesType[i]){                clothes = eval(‘new ‘+ color);   //new Red();            }        }        //判断制造的是不是衣服。        Interface.ensureImplements(clothes, Clothes);        //出售        return clothes;    }}/*门店1var clothesShop1 = new ClothesShop();门店2var clothesShop2 = new ClothesShop();门店3var clothesShop3 = new ClothesShop();*/

 

创建一个门店模型。按照这个模型来实例化门店对象,可以创建多个门店clothesShop1,clothesShop2, clothesShop3..每个门店都可以卖各种漂亮颜色红蓝黄绿灰的衣服。type是顾客喜好的颜色,顾客喜欢就买走。哈哈Interface.ensureImplements在鸭式辨型中提过。这里用来检测衣服是否实现了衣服接口(检测商品到底合不合格)。

Interface类

技术分享
var Interface = function (name, methods) {    if(!methods) {        throw new Error(‘Methods is undefined.‘);    }    if(!Array.isArray(methods)) {        throw new Error(‘Methods is not an array.‘);    }    this.name = name;    this.methods = [];    //自定义方法作为类的依据    for(var i = 0, len = methods.length; i < len; i++) {        var method = methods[i];        if(typeof method !== ‘string‘) {            throw new Error(‘Method name expected to be a string.‘);            break;        }        this.methods.push(method);    }}
View Code

ensureImplements方法

技术分享
Interface.ensureImplements = function () {    var canFoundMethods = [];    if(arguments.length < 2) {        throw new Error(‘Arguments is expected at least 2.‘);    }    //取第二个参数("鸭子"的实例),称为参照对象    for(var i = 1, len = arguments.length; i < len; i++) {        var interface = arguments[i];        //遍历参照对象的方法名称,对比检测对象。        for(var j = 0, methodsLength = interface.methods.length; j < methodsLength; j++) {            var method = interface.methods[j];            if(!arguments[0][method] || typeof arguments[0][method] !== ‘function‘) {                //检测对象没有的方法名称则记录                canFoundMethods.push(method);            }        }    }    //最后输出没有的方法    if(canFoundMethods.length) {        throw new Error (‘Method ‘ + canFoundMethods.join(‘,‘) + ‘ was not found.‘);    }}
View Code

 

第二步

//衣服接口。衣服是什么?自定义为衣服制造出来的,可以穿,可以洗,可以晒干的。var Clothes = new Interface(Clothes, [make, ware, wash, dry]);

定义一个衣服接口,并且自定义具有这四个特点的就是衣服。接口就是一个规则,用来检测对象具有某些方法的手段。

 

//定义红色衣服的模型。var Red = function (){};Red.prototype = {    color: function (){return ‘Red‘;},    make: function (){},    ware: function (){},    wash: function (){},    dry: function (){}}

定义衣服模型。按照这个模型可以生产很多红色的衣服

clothes = eval(‘new ‘+ color);

但是这里还需要经过接口类方法的检测,有没有实现衣服接口。

Interface.ensureImplements(clothes, Clothes);

第三步

//按照衣服门面店的模型,创建一个衣服店。当然也可以创建N个店,clothesShop1,clothesShop2...var clothesShop = new ClothesShop();//指定你要的选的颜色,买新的衣服var yourNewClothes = clothesShop.sellClothes(‘Red‘);

当clothesShop调用sellClothes方法时,就像顾客下订单,然后由店来生产衣服,检测,最后出售。简单的工厂模式完成了,可以高兴一下。但是还是存在着一点问题,这里存在clothesShop既是门店,也是生产衣服的工厂。明显不符合我们的逻辑。我们肯定想的是把工厂和门店要分开。


 

第四步

//===============工厂制造衣服==================//把制造工作交给工厂,商店只负责出售衣服,分工明确。var clothesFactory = {    createClothes: function (color) {        var clothesType = [‘Red‘, ‘Blue‘, ‘Yello‘, ‘Green‘, ‘Gray‘];        var clothes;        for(var i = 0, len = clothesType.length; i < len; i++) {            if(color === clothesType[i]){                clothes = eval(‘new ‘+ color);   //new Red();            }        }        //判断制造的是不是衣服。        Interface.ensureImplements(clothes, Clothes);        //衣服出厂        return clothes;    }}

用一个工厂对象来实现createClothes方法。

 

第五步

//创建一个衣服门店模型。var ClothesShop = function (){}ClothesShop.prototype = {    sellClothes: function (color){        var clothes = clothesFactory.createClothes(color);        //出售        return clothes;    }}

修改ClothesShop门店模型,只负责出售衣服。到这里简单工厂完成了。

 

完整代码:

clothes.js

技术分享
  1 /**  2  * Created by Song_yc on 2015/2/2.  3  */  4 //创建一个衣服门面店模型。  5 var ClothesShop = function (){}  6 ClothesShop.prototype = {  7     sellClothes: function (color){  8         var clothes = clothesFactory.createClothes(color);  9         //出售 10         return clothes; 11     } 12 } 13 /*门店1 14 var clothesShop1 = new ClothesShop(); 15 门店2 16 var clothesShop2 = new ClothesShop(); 17 门店3 18 var clothesShop3 = new ClothesShop();*/ 19  20 var Interface = function (name, methods) { 21     if(arguments.length !== 2) { 22         throw new Error(‘Interface constructor called with‘ + arguments.length + ‘arguments, but expected exactly 2.‘); 23     } 24     this.name = name; 25     this.methods = []; 26     if(!Array.isArray(methods)) { 27         throw new Error(‘The second argument is expected array object instance of ‘ + typeof method+ ‘.‘); 28     } 29     for(var i = 0, len = methods.length; i < len; i++) { 30         var method = methods[i]; 31         if(typeof method !== ‘string‘) { 32             throw new Error(‘Interface constructor expects method names to be as a string.‘); 33             break; 34         } 35         this.methods.push(method); 36     } 37 } 38  39 Interface.ensureImplements = function () { 40     var canFoundMethods = []; 41     //First to determine argument‘s length. 42     if(arguments.length < 2) { 43         throw new Error(‘Arguments is expected at least 2.‘); 44     } 45     //Second to determine instance class. 46     for(var i = 1, len = arguments.length; i < len; i++) { 47         var interface = arguments[i]; 48         if(interface.constructor !== Interface) { 49             throw new Error(interface.name + ‘object is not instanced of Interface Class.‘); 50         } 51         for(var j = 0, methodsLength = interface.methods.length; j < methodsLength; j++) { 52             var method = interface.methods[j]; 53             if(!arguments[0][method] || typeof arguments[0][method] !== ‘function‘) { 54                 //throw new Error(‘Method ‘ + method + ‘was not found.‘); 55                 canFoundMethods.push(method); 56             } 57         } 58     } 59     //canFoundMethods.forEach(function (methodName) { 60     //    throw new Error(‘Method ‘ + methodName + ‘was not found.‘); 61     //}) 62     if(canFoundMethods.length) { 63         throw new Error (‘Method ‘ + canFoundMethods.join(‘,‘) + ‘ was not found.‘); 64     } 65 } 66 //定义衣服类。衣服是什么?被制造出来的,可以穿,可以洗,可以晒干的。 67 var Clothes = new Interface(‘Clothes‘, [‘make‘, ‘ware‘, ‘wash‘, ‘dry‘]); 68 //定义红色衣服的模型。 69 var Red = function (){}; 70 Red.prototype = { 71     color: function (){return ‘red‘;}, 72     make: function (){}, 73     ware: function (){}, 74     wash: function (){}, 75     dry: function (){} 76 } 77  78 //===============工厂制造衣服================== 79  80 //把制造工作交给工厂,商店只负责出售衣服,分工明确。 81 var clothesFactory = { 82     createClothes: function (color) { 83         var clothesType = [‘Red‘, ‘Blue‘, ‘Yello‘, ‘Green‘, ‘Gray‘]; 84         var clothes; 85         for(var i = 0, len = clothesType.length; i < len; i++) { 86             if(color === clothesType[i]){ 87                 clothes = eval(‘new ‘+ color);   //new Red(); 88             } 89         } 90         //判断制造的是不是衣服。 91         Interface.ensureImplements(clothes, Clothes); 92         //衣服出厂 93         return clothes; 94     } 95 } 96  97 //按照衣服门面店的模型,创建一个衣服店。当然也可以创建N个店,clothes1,clothes2... 98 var clothesShop = new ClothesShop(); 99 //选择喜欢的颜色100 var yourNewClothes = clothesShop.sellClothes(‘Red‘);
View Code

index.html

技术分享
<!DOCTYPE html><html><head lang="en">    <meta charset="UTF-8">    <title></title></head><body><script src="http://www.mamicode.com/Interface类.js"></script><script src="http://www.mamicode.com/Interface.ensureImplements方法.js"></script><script src="http://www.mamicode.com/衣服店.js"></script></body></html>
View Code

最后看看新的衣服。

技术分享

 

2.总结:

回顾一下:首先创建一个门店模型,拥有生产各色衣服的方法。然后定义衣服接口,创建红色衣服模型,通过接口检测衣服是否合格。实例化门店,门店按照顾客的喜好进行生产衣服,检测,出售。最后把门店生产独立设计成简单工厂,生产和门店分离。

  • 简单工厂方法就是把创建类实例的方法放在外部对象,当实例化对象时在外部对象中进行。

工厂模式一之简单工厂