工厂模式一之简单工厂

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

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;
    }
}
/*门店1
var clothesShop1 = new ClothesShop();
*/

 创建一个门店模型。按照这个模型来实例化门店对象,可以创建多个门店clothesShop1,clothesShop2, clothesShop3..每个门店都有各种漂亮颜色红蓝黄绿灰的衣服。顾客通过type决定要买什么样的衣服。假设type为'Red',通过实例化衣服类new Red()来生产红色的衣服。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

第二步:定义衣服接口Clothes。

//衣服接口。衣服是什么?自定义为衣服制造出来的,可以穿,可以洗,可以晒干的。
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 (){}
}

定义衣服模型。按照这个模型可以生产很多红色的衣服new Red()。当然这里也可以是其它的衣服模型var Green = function (){},Green.prototype = {..};

第三步:实例化ClothesShop类,调用sellClothes方法。

//按照衣服门面店的模型,创建一个衣服店。当然也可以创建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;
    }
}

用一个名为clothesFactory的工厂对象来实现createClothes方法。这样要需要的时候就可以在sellClothes调用createClothes方法。

第五步:修改ClothesShop类

//创建一个衣服门店模型。
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="clothes.js"></script>
</body>
</html>
View Code

最后看看新的衣服。

2.总结:

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

  • 简单工厂方法就是把创建类实例的方法放在外部对象,当实例化对象时在外部对象中进行。
posted @ 2015-02-02 22:11  Songyc  阅读(291)  评论(0编辑  收藏  举报