工厂模式设计

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>工厂设计模式</title>
        
        <!-- 
        @theme: javascript高级 工厂模式设计
        @autor:EthanCoco
        @date:2015-11-21
        @email:lijianlin0204@163.com
        -->
        
        
        
        <script type=text/javascript charset=utf-8>
        //创建一个命名空间
        var LJL = {};
        
        /**
        *建一个接口
        *接口需要两个参数
        *参数1: 接口的名字(string)
        *参数2: 方法名称(数组(string))
        */
        LJL.Interface = function(name,methods){
            if(arguments.length !== 2){//判断接口参数个数是否正确
                throw new Error("参数个数不正确!");
            }
            this.name = name;
            this.methods = [];//定义一个内置的空数组接受方法名称里的元素
            for(var i = 0;i < methods.length;i++){
                if(typeof methods[i] !== 'string'){
                    throw new Error("方法名称错误,必须是字符串类型!");
                }
                //把传入参数的元素全部放到内置的methods中去
                this.methods.push(methods[i]);
            }
            
        };
        
        /**
        *接口静态方法
        *参数:object
        *检验接口里的方法是否实现
        *如果通过不做任何操作,如果不通过,抛出error
        *目的:检测方法是否全部实现
        *object 要求参数必须有两个以上
        *一个是对象实例
        *其它是要检验的接口对象
        */
        LJL.Interface.checkMethodsIsPass = function(object){
            if(arguments.length < 2){//判断参数,如果参数小于2,抛出异常
                throw new Error("要求参数必须有两个以上@param1=实例对象,其它参数是接口对象!");
            }
            //获得接口实例对象
            for(var i = 1;i<arguments.length;i++){//i=1是因为第二个参数是需要检测的接口
                var  instanceInterface = arguments[i];
                //判断参数是否是接口对象
                if(instanceInterface.constructor !== LJL.Interface){
                    throw new Error("参数是不是接口对象!");
                }
                //如果是,检测接口对象里的方法是否实现
                for(var j = 0;j<instanceInterface.methods.length;j++){
                    //用历史变量接受一个方法的名称,名称是字符串,如果不是就抛出error
                    var methodName = instanceInterface.methods[j];
                    //object[key]表示的就是方法
                    //方法是一个函数,需要判断
                    if(!object[methodName] || typeof object[methodName] !== 'function'){
                        throw new Error("这个方法 '" + methodName + "' 找不到!");
                    } 
                }
            
            }
            
        };
        
        /**
         * 继承方法
         * @param {Object} sub
         * @param {Object} sup
         */            
        LJL.extend=function(sub ,sup){
             // 目的: 实现只继承父类的原型对象
             var F = new Function();    // 1 创建一个空函数    目的:空函数进行中转
             F.prototype = sup.prototype; // 2 实现空函数的原型对象和超类的原型对象转换
             sub.prototype = new F();     // 3 原型继承 
             sub.prototype.constructor = sub ; // 4还原子类的构造器
             //保存一下父类的原型对象: 一方面方便解耦  另一方面方便获得父类的原型对象
             sub.superClass = sup.prototype; //自定义一个子类的静态属性 接受父类的原型对象
             //判断父类的原型对象的构造器 (加保险)
             if(sup.prototype.constructor == Object.prototype.constructor){
                sup.prototype.constructor = sup ; //手动欢迎父类原型对象的构造器
             }
        };
        
        
        ////////////////////////////////////////////////
        //以上都是为工厂设计模式做必要的准备
        ////////////////////////////////////////////////
        
        //思路整理
        /**
        *设计一个买电脑的工厂设计模式
        *首先,得有一个“工厂”;
        *其次,工厂用来“生产电脑”;
        *然后,电脑需要“卖出去”;
        *继续,卖出去需要一个“专卖店”
        *最后,买电脑的人到什么样的商店去“买什么样的电脑”
        */
        
        //生产电脑的工厂 目的:生产电脑
        var PCFactory = {
            //里面有生产电脑的方法
            createPC : function(type){//type 动态生产电脑类型,即客户需要的电脑生产
                //利用eval动态创建传入类型的实例对象
                var pc = eval('new '+type+'()');
                //电脑在生产的时候就需要检测是否合格!
                //第一个参数是电脑的实例对象
                //第二个参数是接口的实例对象
                LJL.Interface.checkMethodsIsPass(pc,PCInterface);
                return pc;
            }
        };
        
        //创建接口实例对象
        //接口需要有两个参数
        //一个是接口的实例对象,一个是方法(数组),open(开机),run(运行)
        var PCInterface = new LJL.Interface('PCInterface',['open','run']);
        
        //创建一个电脑的基类
        function BasePC(){}
        //在原型对象上实现方法
        BasePC.prototype = {
            constructor : BasePC,//还原构造器
            open : function(){
                alert(this.constructor.name + "...open");
            },
            run : function(){
                alert(this.constructor.name + "...run");
            }
        };

    
        //电脑有不同的品牌,不同的专卖店提供不同的电脑
        //创建一个抽象的基类专卖店
        function PCShop(){}
        PCShop.prototype = {
            constructor : PCShop ,
            //买电脑的方法
            sellPC:function(type){
                this.abstractSellPC(type);
            } ,
            abstractSellPC: function(){
                throw new Error('this method is abstract...');
            }
        };
        
        //创建不同品牌的专门店
        
        
        
///////////////////////////////////////////////////            
        //戴尔专卖店
        function DellPCShop(){}
        //每个店都有卖电脑的方法,所以我们继承PCShop里的方法
        LJL.extend(DellPCShop,PCShop);
        //电脑专卖店有不同型号的dell电脑
        DellPCShop.prototype = {
            constructor : DellPCShop,
            sellPC : function(type){
                var pc ;
                var pctypes = ['dellx1','dellx5','dellx8'];//所有dell电脑的型号
                for(i in pctypes){
                    //判断商店是否有你要的型号
                    if(pctypes[i] === type){
                        pc = PCFactory.createPC(type);
                        break;
                    }else{
                        throw new Error("没有你要的型号!");
                    }
                }
                return pc;
            }
        };
        
        //dell电脑不同型号的方法检测实现
        //检测不同品牌的电脑
        function dellx1(){} 
        LJL.extend(dellx1,BasePC); //继承基类的方法
        
        function dellx5(){} 
        LJL.extend(dellx5,BasePC);
        
        function dellx8(){} 
        LJL.extend(dellx8,BasePC);
//////////////////////////////////////////////    



        var shop = new DellPCShop();
        var pc = shop.sellPC('dellx1');
        pc.open();
        </script>
    </head>
    <body>
    </body>
</html>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 207,248评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,681评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,443评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,475评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,458评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,185评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,451评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,112评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,609评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,083评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,163评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,803评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,357评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,357评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,590评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,636评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,925评论 2 344

推荐阅读更多精彩内容