• JavaScript设计模式


    1、JavaScript实现接口

      方法1:注释

        //interface Composite{
        //    function add(obj);
        //    function remove(obj);
        //    function update(obj);
        //}
        
        //CompositeImpl必须实现add remove update 3个方法
        function CompositeImpl(){}
        CompositeImpl.prototype.add=function(obj){};
        CompositeImpl.prototype.remove=function(obj){};
        CompositeImpl.prototype.update=function(obj){};
        
        var c1 = new CompositeImpl();
        var c2 = new CompositeImpl();

      方法2:属性检测

        function CompositeImpl(){
            //显式的在类的内部接受所实现的接口
            //一般来说在类的内部要定义一个变量,接收实现接口的名字
            this.implementsInterface = ["Composite","FormItem"];
        }
        CompositeImpl.prototype.add=function(obj){};
        CompositeImpl.prototype.remove=function(obj){};
        CompositeImpl.prototype.update=function(obj){};
        CompositeImpl.prototype.select=function(obj){};
        //检测函数
        function CheckCompositeImpl(instance){
            //判断当前对象是否实现了所有的接口
            if(!IsImplements(instance,"Composite","FormItem")){
                throw new Error("没有实现所有的方法");
            }
        }
        //公用的具体的检测方法 核心方法
        function IsImplements(obj){
            for(var i=1;i<arguments.length;i++){
                var interfaceName = arguments[i];
                var interfaceFound = false;
                for(var j=0;j<obj.implementsInterface.length;j++){
                    if(obj.implementsInterface[j] == interfaceName){
                        interfaceFound=true;
                        break;
                    }
                }
                if(!interfaceFound){
                    return false;
                }
            }
            return true;
        }
        
        var c1=new CompositeImpl();
        CheckCompositeImpl(c1);

      方法3:鸭式辩型

        类实现接口的目的就是要把接口里面所有的方法都实现

        鸭式辩型核心的核心就是检测方法

       //1、接口类 用来实例化接口
        //需要两个参数 1、接口名字 2、方法名数组
        function Interface(name,methods){
            if(arguments.length != 2){
                throw new Error("该接口实例化对象构造函数参数不是2");
            }
            this.name = name;
            this.method = [];
            
            for(var i=0,len=methods.length;i<len;i++){
                if(typeof methods[i] !== “string”){
                    throw new Error("接口方法名不是string类型");
                }
                this.methods.push(methods[i]);
            }
        }
        Interface.ensureImplements = function(obj){
            if(arguments.length < 2){
                throw new Error("ensureImplements参数个数为"+arguments.length+",不符合要求");
            }
            
            for(var i=1;i<arguments.length;i++){
                var instanceInterface = arguments[i];
                if(instanceInterface.constructor !== Interface){
                    throw new Error("参数类型不是Interface接口类型");
                }
                for(var j=0;j<instanceInterface.methods.length;j++){
                    var methodName=instanceInterface.methods[j];
                    if(!obj[methodName] || typeof object[methodName]!="function"){
                        throw new Error(methodName+"方法没有实现或者不是函数类型");
                    }
                }
            }
        };
        
        
        function CompositeImpl(){
            
        }
        CompositeImpl.prototype.add=function(obj){};
        CompositeImpl.prototype.remove=function(obj){};
        CompositeImpl.prototype.update=function(obj){};
        CompositeImpl.prototype.select=function(obj){};    
        
        var CompositeInterface = new Interface("CompositeInterface",["add","remove"]);
        var FormItemInerface = new Interface("FormItemInerface",["update","select"]);
        
        var c1 = new CompositeImpl();
        Interface.ensureImplements(c1,CompositeInterface,FormItemInerface);

    2、单体模式

        //简单单体
        var Singleton={
            attr1:true,
            attr2:10,
            method1:function(){
                alert("方法一");
            },
            method2:function(){
                alert("方法二");
            }
        };
        alert(Singleton.attr1);    
        //借助闭包创建单体 闭包的主要目的是保护数据 拥有自己的作用域
        var BHX={};
        BHX.Singleton=(function(){
            //在这个作用域里面可以添加自己的成员
            var a1=true;
            var a2=10;
            function f1(){
                alert("f1");
            }
            function f2(){
                alert("f2");
            }
            
            return {
                attr1:a1,
                attr2:a2,
                method1:f1,
                method2:f2
            };
        })();
    alert(BHX.Singleton.attr1);
    //惰性单体 和闭包单体有一些相似的地方
        var Ext={};
        Ext.Base=(function(){
            var uniqInstance;
            
            function init(){
                var a1=10;
                var a2=true;
                var fn1=function(){alert("fn1");};
                var fn2=function(){alert("fn2");};
    
                return {
                    attr1:a1,
                    attr2:a2,
                    method1:fn1,
                    method2:fn2
                };
            }
            
            return {
                getInstance:function(){
                    if(!uniqInstance){
                        uniqInstance=init();
                    }
                    return uniqInstance;
                },
            };
        })();
        alert(Ext.Base.getInstance().attr1);
    //分支单体 判断程序的分支 和switch类似
        var Ext={};
        var diff=true;
        Ext.More=(function(){
            var objA={
                attr1:"FF"
            };
            var objB={
                attr1:"IE"
            };
            return def ? objA : objB;
        })();
        alert(Ext.More.attr1);

    3、函数链式调用

        function Dog(){
            this.run=function(){
                alert("Dog is running");
                return this;
            };
            this.eat=function(){
                alert("Dog is eating");
                return this;
            };
            this.sleep=function(){
                alert("Dog is sleeping");
                return this;
            };
        }
        var d1=new Dog();
        d1.run();
        d1.sleep();
        d1.eat();
        //==================jquery模拟
        (function(){
            function _$(arguments){
                var idSel=/^#w+/;
                this.dom;
                
                if(idSel.test(arguments[0])){
                    this.dom=document.getElementById(arguments[0].substring(1));
                }else{
                    throw new Error("无法匹配id");
                }
            }
            
            Function.prototype.method=function(methodName,fn){
                this.prototype[methodName]=fn;
                return this;
            };
            
            _$.prototype={
                constructor:_$,
                addEvent:function(){},
                setStyle:function(){}
            };
            
            _$.onReady=function(fn){
                window.$=function(){
                    return new _$(arguments);
                };
                fn();
                _$.method("addEvent",function(){
                    return this;
                }).method("setStyle",function(){
                    return this;
                });
            };
            
            window.$=_$;
        })(window);
        
        $.onReady(function(){
            $("#inp")
        });

    4、工厂方式

        function CarShop(){
            
        }
        CarShop.prototype={
            constructor:CarShop,
            sellCar:function(type){
                var car=CarFactory.createCar(type);
                return car;
                //这是生产车的逻辑,所以不应该出现在这里
                //var car;
                //switch(type){
                //    case "Benz":
                //        car=new Benz();
                //        break;
                //    case "Bmw":
                //        car=new Bmw();
                //        break;
                //    case "Audi":
                //        car=new Audi();
                //        break;
                //    default:
                //        "没有合适的车";
                //}
                //Interface.ensureImplements(car,CarInterface);
                //return car;
            },
        };
        
        var CarInterface = new Interface("CarInterface",["start","run"]);
        
        function BaseCar(){}
        BaseCar.prototype={
            constructor:BaseCar,
            start:function(){},
            run:function(){}
        };
        
        function Benz(){}
        extend(Benz,BaseCar);
        
        function Bmw(){}
        extend(Bmw,BaseCar);
        
        function Audi(){}
        extend(Audi,BaseCar);
        
        var shop=new CarShop();    
        var car=shop.sellCar("Benz");
        car.start();
        car.run();
        
        //注:在CarShop的sellCar方法中,既有卖车的逻辑,又有生产车的逻辑(new Benz() new Bmw()...)
        //生产车的逻辑应该交给工厂来做
        //生产一台车,单体模式
        var CarFactory={
            createCar:function(){
                var car;
                switch(type){
                    case "Benz":
                        car=new Benz();
                        break;
                    case "Bmw":
                        car=new Bmw();
                        break;
                    case "Audi":
                        car=new Audi();
                        break;
                    default:
                        "没有合适的车";
                }
                Interface.ensureImplements(car,CarInterface);
                return car;
            }
        };
    ==================复杂工厂(真正的工厂)================
        //买什么车去什么商店->商店->卖车->生产车->工厂
        //需要一个商店抽象类,将CarShop作为抽象类
        function CarShop(){}
        CarShop.prototype={
            constructor:CarShop,
            sellCar:function(type){
                //var car=CarFactory.createCar(type);
                //return car;
                this.abstractSellCar(type);
            },
            abstractSellCar:function(){
                throw new Error("抽象类不可以直接调用");
            }
        };
        
        function BenzCarShop(){}
        extend(BenzCarShop,CarShop);
        BenzCarShop.prototype={
            constructor:BenzCarShop,
            sellCar:function(type){
                var car;
                var types=["Benz"];
                for(var t in types){
                    if(types[t]===type){
                        car=CarFactory.createCar(type);
                    }else{
                        alert("没有对应的车型号");
                    }
                }
                return car;
                //var car=CarFactory.createCar(type);
                //return car;
            }
        };
        
        function BmwCarShop(){}
        extend(BmwCarShop,CarShop);
        BmwCarShop.prototype={
            constructor:BmwCarShop,
            sellCar:function(type){
                var car;
                var types=["Bmw"];
                for(var t in types){
                    if(types[t]===type){
                        car=CarFactory.createCar(type);
                    }else{
                        alert("没有对应的车型号");
                    }
                }
                return car;
                //var car=CarFactory.createCar(type);
                //return car;
            }
        };
        
        var CarInterface = new Interface("CarInterface",["start","run"]);
        
        function BaseCar(){}
        BaseCar.prototype={
            constructor:BaseCar,
            start:function(){},
            run:function(){}
        };
        
        function Benz(){}
        extend(Benz,BaseCar);
        
        function Bmw(){}
        extend(Bmw,BaseCar);
        
        function Audi(){}
        extend(Audi,BaseCar);
        
        var CarFactory={
            createCar:function(){
                //利用eval动态创建传入类型的实例对象
                var car=eval("new "+type+"()");
                Interface.ensureImplements(car,CarInterface);
                return car;
            }
        };
        
        var shop1=new BenzCarShop();
        var car1=shop1.sellCar();
        car1.run();

    5、桥接模式

    桥接模式
        事件绑定
        window.onload=function(){
            var oInput=document.getElementById("ipt");
            oInput.addEventListener("click",sendReq,false);
            
            function sendReq(){
                $.post("URL",{msg:"abc"},function(result){
                    
                });
            }
        };
        特权函数 使内部和外部解耦
        function Public(){
            var name="张三";
            this.getName=function(){
                return name;
            };
        }
        
        var p1=new Public();
        alert(p1.getName());
        ===============
        function Public(){
            var privateMethod=function(){
                alert("复杂操作");
            };
            
            this.bridgeMethod=function(){
                return privateMethod();
            };
        }
        var p1=new Public();
        p1.bridgeMethod();
        ==============
        用桥把多个单体组织在一起
        使每个单元都能独立化,可以实现自己的变化
        function Class1(a,b,c){
            this.a=a;
            this.b=b;
            this.c=c;
        }
        function Class2(d,e){
            this.d=d;
            this.e=e;
        }
        function BridgeClass(a,b,c,d,e){
            this.class1=new Class1(a,b,c);
            this.class2=new Class2(d,e);
        }

    6、组合模式

      专门为Web上的动态用户界面而量身定制的
      这种模式可以用一条命令在多个对象上激发复杂的或递归的行为
      好处:用同样的方法处理对象的集合与其中的特定子对象
      还可以用来把一批子对象组织成树状结构,并且使整棵树都可以被遍历

    function Org(name){
            this.name=name;
            this.depts=[];
        }
        Org.prototype={
            constructor:Org,
            addDepts:function(child){
                this.depts.push(child);
                return this;
            },
            getDepts:function(){
                return this.depts;
            }
        };
        
        function Dept(name){
            this.name=name;
            this.persons=[];
        }
        Dept.prototype={
            constructor:Dept,
            addPersons:function(child){
                this.persons.push(child);
                return this;
            },
            getPersons:function(){
                return this.persons;
            }
        };
    
        function Person(name){
            this.name=name;
        }
    
        Person.prototype={
            constructor:Person,
            hardworking:function(){
                alert("working");
            },
            sleeping:function(){
                alert("sleeping");
            }
        };
    
        var p1=new Person("张1");
        var p2=new Person("张2");
        var p3=new Person("张3");
        var p4=new Person("张4");
        var p5=new Person("张5");
        var p6=new Person("张6");
    
        var dept1=new Dept("开发部");
        dept1.addPersons(p1).addPersons(p2).addPersons(p3);
        var dept2=new Dept("销售部");
        dept2.addPersons(p4).addPersons(p5).addPersons(p6);
    
        var org=new Org("bjsxt");
        org.addDepts(dept1).addDepts(dept2);
    
        //需求:具体让某个人工作
        for(var i=0,depts=org.getDepts();i<depts.length;i++){
            var dept=depts[i];
            for(var j=0;j<dept.getPersons().length;j++){
                if(dept.getPersons()[j].name==="张3"){
                    dept.getPersons()[j].hardworking();
                }
            }
        }
        //当需求更改为开发部下又分为开发部1 开发部2 开发部3
        //再让某个子开发部的某个人去工作,那么for循环就会再嵌套一层,if判断也更加复杂
        //业务逻辑的更改造成了代码的大幅度变化
        //此时我们可以让组合模式来帮我们
    
        //组合模式应用的场景和特点
        //场景:
        //1、存在一批组织成某种层次体系的对象
        //2、希望对这批对象或其中一部分对象实施一个操作
    
        //特点:
        //组合模式中只有两种类型对象:组合对象、叶子对象
        //这两种类型都实现同一批接口
        //一般我们会在组合对象中调用其方法并隐式调用下级方法,一般会采用递归的形式实现
        
        //组合对象
        function Composite(name){
            this.name=name;
            this.type="Composite";//说明对象的类型
            this.children=[];
        }
        Composite.prototype={
            constructor:Composite,
            addChild:function(child){
                this.children.push(child);
                return this;
            },
            getChild:function(name){
                var elements=[];
                var pushLeaf=function(item){
                    if(item.type === "Composite"){
                        item.children.each(arguments.callee);
                    }else if(item.type === "Leaf"){
                        elements.push(item);
                    }else{
                        throw new Error("类型错误");
                    }
                };
                if(name && this.name !== name){//根据name让指定name下的Leaf对象执行操作
                    this.children.each(function(item){
                        if(item.name === name && item.type === "Composite"){
                            item.children.each(pushLeaf);
                        }else if(item.name !=== name && item.type === "Composite"){
                            item.children.each(arguments.callee);
                        }else if(item.name === name && item.type === "Leaf"){
                            elements.push(item);
                        }
                    });
                }else{//让所有的Leaf结点执行操作
                    //this.children得到的时开发部和销售部
                    this.children.each(pushLeaf);
                }
                return elements;
            },
            hardworking:function(name){
                //得到所有的Leaf类型的对象
                var leafObject=this.getChild(name);
                for(var i=0;i<leafObject.length;i++){
                    leafObject[i].hardworking();
                }
            },
            sleeping:function(name){            
                var leafObject=this.getChild(name);
                for(var i=0;i<leafObject.length;i++){
                    leafObject[i].sleeping();
                }
            }
        };
        //叶子对象
        function Leaf(name){
            this.name=name;
            this.type="leaf";
        }
        Leaf.prototype={
            constructor:Leaf,
            addChild:function(child){
                throw new Error("叶子结点不能添加子对象");
            },
            getChild:function(name){
                if(this.name==name){
                    return this;
                }
                return null;
            },
            hardworking:function(){
                alert(this.name+" working");
            },
            sleeping:function(){
                alert(this.name+" sleeping");
            }
        };
    
        var CompositeInterface=new Interface("CompositeInterface",["getChild","addChild"]);
        var LeafInterface=new Interface("LeafInterface",["hardworking","sleeping"]);
        
        var p1=new Leaf("张1");
        var p2=new Leaf("张2");
        var p3=new Leaf("张3");
        var p4=new Leaf("张4");
        var p5=new Leaf("张5");
        var p6=new Leaf("张6");
    
        var dept1=new Composite("开发部");
        dept1.addChild(p1).addChild(p2).addChild(p3);
        var dept2=new Composite("销售部");
        dept2.addChild(p4).addChild(p5).addChild(p6);
    
        var org=new Composite("bjsxt");
        org.addChild(dept1).addChild(dept2);
        
        org.hardworking("开发部");
        //如果不传参数,就让所有结点调用hardworking方法
        org.hardworking();

    7、门面模式

        //门面模式的两个作用:简化类的接口,消除类和使用它的客户代码之间的耦合
        //是最常用的设计模式
        //最经典的就是事件
        
        //做一件事情 必须调用2个函数 分别是a b
        //其实就是不要把所有的逻辑都写在一个函数里面,要分开写
        function a(x){}
        function b(y){}
        function ab(x,y){
            a(x);
            b(y);
        }

    8、适配器模式

       //现有的接口和不兼容的类之间进行适配。使用这种模式的对象又叫包装器,因为他们是在用一个新的接口包装另一个对象。借助适配器可以处理一些与API不匹配、不能一同使用的情况 
        var obj={
            str1:"111",
            str1:"222",
            str1:"333"
        };
        
        function adapter(obj){
            interfaceMethod(obj.str1,obj.str2,obj.str3);
        }
        
        function interfaceMethod(x,y,z){
            
        }
        ===================
        //假设要兼容YUI和prototype两个库
        function $(){
            var elements=[];
            for(var i=0;i<arguments.length;i++){
                var element=arguments[i];
                if(typeof element === "string"){
                    element=document.getElementById(element);
                }
                if(arguments.length === 1){
                    return element;
                }
                elements.push(element);
            }
            return elements;
        }
        var yahoo={};
        yahoo.get=function(el){
            if(typeof el==="string"){
                return document.getElementById(el);
            }
            if(el instanceof Array){
                var elements=[];
                for(var i=;i<el.length;i++){
                    elements.push(yahoo.get(el[i]));
                }
                return elements;
            }
            if(el){
                return el;
            }
            return null;
        };
        yahoo.get=yuiToPrototypeAdapter;
        function yuiToPrototypeAdapter(){
            if(arguments.length === 1){
                return $.apply(window,e instanceof Array?e:[e]);
            }else{
                return $.apply(window,arguments);//或者用call也行
            }
        }
        window.onload=function(){
            //var domarr=$("inp1","inp2"); prototype风格写法
            //var domarr=yahoo.get(["inp1"]); YUI风格写法
            
            //适配器模式的目的就是要让以下prototype的参数风格传入yahoo框架也可以使用
            yahoo.get("inp1","inp2");
        };

    9、装饰者模式

        //为对象添加新特性的技术
        //实现同样的接口
        //需要有子类
        var CarInterface=new Interface("CarInterface",["getPrice","assemble"]);
        function Car(car){
            //就是为了让子类继承的 让子类多一个父类的引用
            this.car=car;
            //检查接口
            Interface.ensureImplements(this,CarInterface);
        }
        Car.prototype={
            constructor:Car,
            getPrice:function(){
                return 200000;
            },
            assemble:function(){
                alert("组装汽车");
            }
        };
        //如果新的需求需要创建子类,而子类有可能会影响到父类的某些属性
        //这时就要用装饰者模式
        //用来把原始对象包装在具有同样接口的另一个对象中
        function LightDecorator(car){//参数car代表原始对象
            //LightDecorator.superClass是父类的原型对象
            Car.call(this,car);
        }
        extend(LightDecorator,Car);
        
        LightDecorator.prototype={
            constructor:LightDecorator,
            getPrice:function(){
                return this.car.getPrice()+10000;//在子类上修改,没有影响到父类
            },
            assemble:function(){
                alert("组装汽车");
            }        
        };
        
        function IceBoxDecorator(car){
            LightDecorator.call(this,car);
        }
        extend(IceBoxDecorator,Car);
        IceBoxDecorator.prototype={
            constructor:IceBoxDecorator,
            getPrice:function(){
                return this.car.getPrice()+20000;//在子类上修改,没有影响到父类
            },
            assemble:function(){
                alert("组装汽车");
            }    
        };
        
        var car=new Car();
        alert(car.getPrice());
        
        car=new LightDecorator(car);
        alert(car.getPrice());
        
        car=new IceBoxDecorator(car);
        alert(car.getPrice());
        =================================================
        //装饰者模式不仅可以用在类上,还可以用在函数上
        function getDate(){
            return new Date().toString();
        }
        //包装函数
        function upperCaseDecorator(fn){
            return function(){
                return fn.apply(this,arguments).toUpperCase();
            };
        }

    10、享元模式

        //出厂商 出厂日期 拥有者 车牌号 登记日期
        function Car(make,model,year,owner,tag,renewDate){
            this.make=make;
            this.model=model;
            this.year=year;
            this.owner=owner;
            this.tag=tag;
            this.renewDate=renewDate;
        }
        Car.prototype={
            constructor:Car,
            getMake:function(){
                return this.make;
            },
            getModel:function(){
                return this.model;
            },
            getYear:function(){
                return this.year;
            },
            renewRegistration:function(newRenewDate){
                this.renewDate=newRenewDate;
            }
        };
        var arr=[];
        var start=new Date().getTime();
        for(var i=0;i<5000000;i++){
            arr.push(new Car("aaa","bbb","2012","ccc","112233","2013"));
        }
        var end=new Date().getTime();
        alert(end-start);//700多毫秒
        //占用内存大约 570M左右
        
        //我们接下来用享元模式优化它
        //内在数据:可以共享的属性
        //外在数据:不能共享的属性
        //享元模式要把内在数据抽出
        
        
        function Car(make,model,year){
            this.make=make;
            this.model=model;
            this.year=year;
        }
        Car.prototype={
            constructor:Car,
            getMake:function(){
                return this.make;
            },
            getModel:function(){
                return this.model;
            },
            getYear:function(){
                return this.year;
            }
        };
        
        //工厂模式 利用闭包工厂把静态的东西初始化出来
        var CarFactory=(function(){
            //已经生产好的car
            var createdCars={};
            return {
                createCar:function(make,model,year){
                    //如果createdCars对象里已经存在当前的make model year 
                    if(createdCars[make+model+year]){
                        return createdCars[make+model+year];
                    }else{
                        var car=new Car(make,model,year);
                        createCars[make+model+year]=car;
                        return car;
                    }
                }
            };
        })();
        //用单体模式把外在的数据和内在的数据结合在一起
        var CarRecordManager=(function(){
            //把登记号的汽车防盗这个对象里
            var carRecordDataBase={};
            return {
                addCarRecord:function(make,model,year,owner,tag,renewDate){
                    var car=CarFactory.createCar(make,model,year);
                    carRecordDataBase[tag]={
                        owner:owner,
                        renewDate:renewDate,
                        car:car
                    };
                },
                renewRegistration:function(tag,newRenewDate){
                    carRecordDataBase[tag].renewDate=newRenewDate;
                }
            };
        })();
        var arr=[];
        var start=new Date().getTime();
        for(var i=0;i<5000000;i++){
            arr.push(CarRecordManager.addCarRecord("aaa","bbb","2012","ccc","112233","2013"));
        }
        var end=new Date().getTime();
        alert(end-start);//3000-5000多毫秒
        //内存大约占用290M左右
        
        //时间和空间不可兼得
        //模拟web日历 并利用享元模式优化
        var CalendarInterface=new Interface("CalendarInterface",["display"]);
        function CalendarYear(year,parent){
            this.year=year;
            this.element=document.createElement("div");
            this.element.style.display="none";
            parent.appendChild(this.element);
            
            this.months=[];
            this.numDays=[31,isLeapYear(this.year)?29:28,31,30,31,30,31,31,30,31,30,31];
            for(var i=0;i<12;i++){
                this.months[i]=new CalendarMonth(i,this.numDays[i],this.element);
            }
        }
        CalendarYear.prototype={
            constructor:CalendarYear,
            display:function(){
                for(var i=0;i<this.months.length;i++){
                    this.months[i].display();
                }
                this.element.style.display="block";
            }
        };
        function CalendarMonth(monthNum,numDays,parent){
            this.monthNum=monthNum;
            this.element=document.createElement("div");
            this.element.style.display="none";
            parent.appendChild(this.element);
            
            this.days=[];
            
            for(var i=0;i<numDays;i++){
                this.days[i]=new CalendarDay(i+1,this.element);
            }
        }
        CalendarMonth.prototype={
            constructor:CalendarMonth,
            display:function(){
                for(var i=0;i<this.days.length;i++){
                    this.days[i].display();
                }
                this.element.style.display="block";
            }
        };
        function CalendarDay(date,parent){
            this.date=date;
            this.element=document.createElement("div");
            this.element.style.display="none";
            parent.appendChild(this.element);
        }
        CalendarDay.prototype={
            constructor:CalendarDay,
            display:function(){
                this.element.style.display="block";
                this.element.innerHTML=this.date;
            }
        };
    
        function isLeapYear(y){
            return (y>0) && !(y%4) && ((y%100) || !(y%400));
        }
        
        window.onload=function(){
            var mydiv=document.getElementById("mydiv");
            var myyear=new CalendarYear(2014,mydiv);
            myyear.display();
            
            //一年都要new出来365个对象,年多了性能就很差了
        };
        
        <div id="mydiv"></div>
    
        //享元模式优化上面的日历 主要优化天对象
        function CalendarMonth(monthNum,numDays,parent){
            this.monthNum=monthNum;
            this.element=document.createElement("div");
            this.element.style.display="none";
            parent.appendChild(this.element);
            
            this.days=[];
            
            for(var i=0;i<numDays;i++){
                //只用这一个实例
                this.days[i]=calendarDaySingleInstance;
            }
        }
        CalendarMonth.prototype={
            constructor:CalendarMonth,
            display:function(){
                for(var i=0;i<this.days.length;i++){
                    this.days[i].display(i+1,this.element);
                }
                this.element.style.display="block";
            }
        };
        
        function CalendarDay(){}
        CalendarDay.prototype={
            constructor:CalendarDay,
            display:function(date,parent){
                var element=document.createElement("div");
                parent.appendChild(element);
                element.style.display="block";
                element.innerHTML=date;
            }
        };
        var calendarDaySingleInstance=new CalendarDay();
  • 相关阅读:
    [netty] netty中的定时机制HashedWheelTimer 规格严格
    c和c++开发工具之clion和vs
    编译python(cpython)的源码及其用途
    python缩进tab和空格互转
    c和c++编译器之gcc和mingw
    DotLiquid(.net模版引擎)
    微信公众号自定义菜单的一些思考我为什么做公众号自定义菜单
    Owner项目步骤
    xx系统分析说明书
    项目经理养成计划
  • 原文地址:https://www.cnblogs.com/zhaohuiziwo901/p/5269338.html
Copyright © 2020-2023  润新知