zoukankan      html  css  js  c++  java
  • 工厂模式一之简单工厂

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

    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.总结:

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

    • 简单工厂方法就是把创建类实例的方法放在外部对象,当实例化对象时在外部对象中进行。
  • 相关阅读:
    集合总结
    dagger2系列之Scope
    dagger2系列之依赖方式dependencies、包含方式(从属方式)SubComponent
    dagger2系列之生成类实例
    Dagger2系列之使用方法
    Handler系列之内存泄漏
    Handler系列之创建子线程Handler
    Handler系列之原理分析
    Handler系列之使用
    HTML标签
  • 原文地址:https://www.cnblogs.com/Songyc/p/4268194.html
Copyright © 2011-2022 走看看