工厂模式设计

2017-09-27  本文已影响0人  小建哥哥
<!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>
上一篇 下一篇

猜你喜欢

热点阅读