zoukankan      html  css  js  c++  java
  • 工厂模式二之真正工厂

    简单工厂是将商店和工厂分开,把工厂生产的放到另外的一个clothesFactory对象中调用createClothes方法进行。这一节我们要实现真正的工厂。

    回顾一下简单工厂的实现:

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

    这里我们只要上面的代码,clothesFactory工厂对象不要了。

    //创建一个衣服门面店模型。
    var ClothesShop = function (){}
    ClothesShop.prototype = {
        sellClothes: function (color){
            var clothes = clothesFactory.createClothes(color);
            //出售
            return clothes;
        }
    }
    
    var Interface = function (name, methods) {
        if(arguments.length !== 2) {
            throw new Error('Interface constructor called with' + arguments.length + 'arguments, but expected exactly 2.');
        }
        this.name = name;
        this.methods = [];
        if(!Array.isArray(methods)) {
            throw new Error('The second argument is expected array object instance of ' + typeof method+ '.');
        }
        for(var i = 0, len = methods.length; i < len; i++) {
            var method = methods[i];
            if(typeof method !== 'string') {
                throw new Error('Interface constructor expects method names to be as a string.');
                break;
            }
            this.methods.push(method);
        }
    }
    
    Interface.ensureImplements = function () {
        var canFoundMethods = [];
        //First to determine argument's length.
        if(arguments.length < 2) {
            throw new Error('Arguments is expected at least 2.');
        }
        //Second to determine instance class.
        for(var i = 1, len = arguments.length; i < len; i++) {
            var interface = arguments[i];
            if(interface.constructor !== Interface) {
                throw new Error(interface.name + 'object is not instanced of Interface Class.');
            }
            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') {
                    //throw new Error('Method ' + method + 'was not found.');
                    canFoundMethods.push(method);
                }
            }
        }
        //canFoundMethods.forEach(function (methodName) {
        //    throw new Error('Method ' + methodName + 'was not found.');
        //})
        if(canFoundMethods.length) {
            throw new Error ('Method ' + canFoundMethods.join(',') + ' was not found.');
        }
    }
    //定义衣服类。衣服是什么?被制造出来的,可以穿,可以洗,可以晒干的。
    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 (){}
    }

    现实生活的衣服店大多数不是专卖店,它经营的商品可来自几个不同的供应商,我们称为杂牌店,杂牌店里可能看到张三供应商,李四供应商的。衣服的来源五花八门,所以这里就不再是单一的clothesFactory对象生产的,用this代替。

    ClothesShop.prototype = {
        sellClothes: function (color){
            var clothes = this.createClothes(color);
            //出售
            return clothes;
        }
    }

    供应商类

    var zhangshanClothesShop = function (){};
    extend(zhangshanClothesShop, ClothesShop);

    创建张三供应商类zhangshanClothesShop, 供应商类继承了门店类。于是子类拥有了父类的方法。因为门店进货也有自已的标准啊,不是什么货都随便要的。供应商生产的衣服要按照门店的要求生产。所以要继承它的方法。

    extend函数

    function extend(subClass, superClass){
        var F = function () {};
        F.prototype = superClass.prototype;
        subClass.prototype = new F();
        subClass.prototype.constructor = subClass;
    }

    最后供应商生产

    zhangshanClothesShop.prototype.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;
    }

    供应商类zhangshanClothesShop通过实例化,调用createClothes方法就可以生产clothes。

    var zhangshanClothesshop = new zhangshanClothesShop();
    var yourNewClothes = zhangshanClothesshop.sellClothes('Red');

    如果全部由zhangshanClothessshop调用createClothes,那么我们的门店就是一家专卖店,张三衣服专卖店。在实例化Blue之前,还要创建Blue类。

    var Blue = function (){};
    Blue.prototype = {
        color: function (){return 'blue';},
        make: function (){},
        ware: function (){},
        wash: function (){},
        dry: function (){}
    }
    var yourNewClothes = zhangshanClothesshop.sellClothes('Red');
    var yourNewClothes2 = zhangshanClothesshop.sellClothes('Blue');
    //var yourNewClothes3 = zhangshanClothesshop.sellClothes('Yellow');
    //var yourNewClothes4 = zhangshanClothesshop.sellClothes('Green');
    //var yourNewClothes5 = zhangshanClothesshop.sellClothes('Gray');

    我们想要多个品牌的衣服,那就要从不同的供应商进货。只要创建多个供应商类就可以了。

    //李四
    var lisiClothesShop = function (){};
    extend(lisiClothesShop, ClothesShop);
    
    lisiClothesShop.prototype.createClothes = function (color){
        var clothesType = ['Red', 'Blue', 'Yellow', '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;
    }
    var lisiClothesshop = new lisiClothesShop();
    var myNewClothes = lisiClothesshop.sellClothes('Red');

    虽然myNewClothes和yourNewClothes同样是衣服对象,都是红色的衣服,都具有相同的方法make,ware,wash等,只是出自于不同的供应商或者说是不同的工厂生产的。这就是唯一的区别。工厂模式是用子类通过类继承(extend方法),拥有父类的方法。再通过实例化子类对象,调用父类方法来实现父类要完成的工作。这样做是为了降低类与类的耦合,似乎把一个人的工作分给两个人来做,变得轻松和灵活。

    完整代码:

    factory.js

      1 //创建一个衣服门面店模型。
      2 var ClothesShop = function (){}
      3 ClothesShop.prototype = {
      4     sellClothes: function (color){
      5         var clothes = this.createClothes(color);
      6         //出售
      7         return clothes;
      8     }
      9 }
     10 
     11 var Interface = function (name, methods) {
     12     if(arguments.length !== 2) {
     13         throw new Error('Interface constructor called with' + arguments.length + 'arguments, but expected exactly 2.');
     14     }
     15     this.name = name;
     16     this.methods = [];
     17     if(!Array.isArray(methods)) {
     18         throw new Error('The second argument is expected array object instance of ' + typeof method+ '.');
     19     }
     20     for(var i = 0, len = methods.length; i < len; i++) {
     21         var method = methods[i];
     22         if(typeof method !== 'string') {
     23             throw new Error('Interface constructor expects method names to be as a string.');
     24             break;
     25         }
     26         this.methods.push(method);
     27     }
     28 }
     29 
     30 Interface.ensureImplements = function () {
     31     var canFoundMethods = [];
     32     //First to determine argument's length.
     33     if(arguments.length < 2) {
     34         throw new Error('Arguments is expected at least 2.');
     35     }
     36     //Second to determine instance class.
     37     for(var i = 1, len = arguments.length; i < len; i++) {
     38         var interface = arguments[i];
     39         if(interface.constructor !== Interface) {
     40             throw new Error(interface.name + 'object is not instanced of Interface Class.');
     41         }
     42         for(var j = 0, methodsLength = interface.methods.length; j < methodsLength; j++) {
     43             var method = interface.methods[j];
     44             if(!arguments[0][method] || typeof arguments[0][method] !== 'function') {
     45                 //throw new Error('Method ' + method + 'was not found.');
     46                 canFoundMethods.push(method);
     47             }
     48         }
     49     }
     50     //canFoundMethods.forEach(function (methodName) {
     51     //    throw new Error('Method ' + methodName + 'was not found.');
     52     //})
     53     if(canFoundMethods.length) {
     54         throw new Error ('Method ' + canFoundMethods.join(',') + ' was not found.');
     55     }
     56 }
     57 //定义衣服类。衣服是什么?被制造出来的,可以穿,可以洗,可以晒干的。
     58 var Clothes = new Interface('Clothes', ['make', 'ware', 'wash', 'dry']);
     59 //定义红色衣服的模型。
     60 var Red = function (){};
     61 Red.prototype = {
     62     color: function (){return 'red';},
     63     make: function (){},
     64     ware: function (){},
     65     wash: function (){},
     66     dry: function (){}
     67 }
     68 
     69 var Blue = function (){};
     70 Blue.prototype = {
     71     color: function (){return 'blue';},
     72     make: function (){},
     73     ware: function (){},
     74     wash: function (){},
     75     dry: function (){}
     76 }
     77 
     78 function extend(subClass, superClass){
     79     var F = function () {};
     80     F.prototype = superClass.prototype;
     81     subClass.prototype = new F();
     82     subClass.prototype.constructor = subClass;
     83 }
     84 
     85 //张三类
     86 var zhangshanClothesShop = function (){};
     87 //张三类供应商按照商店要求模型生产自行车模型。
     88 extend(zhangshanClothesShop, ClothesShop);
     89 
     90 zhangshanClothesShop.prototype.createClothes = function (color){
     91     var clothesType = ['Red', 'Blue', 'Yellow', 'Green', 'Gray'];
     92     var clothes;
     93     for(var i = 0, len = clothesType.length; i < len; i++) {
     94         if(color === clothesType[i]){
     95             clothes = eval('new '+ color);   //new Red();
     96         }
     97     }
     98     //检测。
     99     Interface.ensureImplements(clothes, Clothes);
    100     //衣服出厂
    101     return clothes;
    102 }
    103 //按照衣服门面店的模型,创建一个衣服店。当然也可以创建N个店,clothes1,clothes2...
    104 var zhangshanClothesshop = new zhangshanClothesShop();
    105 //选择喜欢的颜色
    106 var yourNewClothes = zhangshanClothesshop.sellClothes('Red');
    107 var yourNewClothes2 = zhangshanClothesshop.sellClothes('Blue');
    108 //var yourNewClothes3 = zhangshanClothesshop.sellClothes('Yellow');
    109 //var yourNewClothes4 = zhangshanClothesshop.sellClothes('Green');
    110 //var yourNewClothes5 = zhangshanClothesshop.sellClothes('Gray');
    111 
    112 
    113 //李四
    114 var lisiClothesShop = function (){};
    115 extend(lisiClothesShop, ClothesShop);
    116 
    117 lisiClothesShop.prototype.createClothes = function (color){
    118     var clothesType = ['Red', 'Blue', 'Yellow', 'Green', 'Gray'];
    119     var clothes;
    120     for(var i = 0, len = clothesType.length; i < len; i++) {
    121         if(color === clothesType[i]){
    122             clothes = eval('new '+ color);   //new Red();
    123         }
    124     }
    125     //检测。
    126     Interface.ensureImplements(clothes, Clothes);
    127     //衣服出厂
    128     return clothes;
    129 }
    130 var lisiClothesshop = new lisiClothesShop();
    131 var myNewClothes = lisiClothesshop.sellClothes('Red');
    View Code

    index.html

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    
    <script src="factory.js"></script>
    </body>
    </html>
    View Code

    总结:

    通过衣服店的例子,简单地讨论了简单工厂和真正工厂模式。简单工厂是通过另一个对象的方法或者类的实例化来完成工作。而真正工厂是把类的实现方法交给子类实例化进行的,降低对象间的耦合,消除不必要的代码执行。这种模式用于实现比较复杂的代码结构,越复杂越体现其优越性。子类的创建会让分工变得更加明细。

  • 相关阅读:
    【转】PostgreSQL中表名、字段名大小写问题
    【转】 PostgreSQL数据类型
    ASP.NET MVC 使用 Petapoco 微型ORM框架+NpgSql驱动连接 PostgreSQL数据库(问题总结)
    mvc项目中实现备份数据库(sqlserver2012)
    定时器的使用
    ASP.NET MVC向前台输出javascript问题
    无法从命令行或调试器启动服务,必须首先安装Windows服务(使用installutil.exe),然后用ServerExplorer、Windows服务器管理工具或NET START命令启动它
    标签控制器  UITabBarController
    UITableView动态存放、重用机制
    UITableView表格视图、UITableView代理方法及应用
  • 原文地址:https://www.cnblogs.com/Songyc/p/4271215.html
Copyright © 2011-2022 走看看