美文网首页
JavaScript常用设计模式

JavaScript常用设计模式

作者: 不知所Yun | 来源:发表于2019-04-12 10:11 被阅读0次

开放封闭原则:

开放性:当有新需求时,可以对现有代码进行扩展,在不影响现有功能的前提下,来实现新需求;

封闭性:模块的源代码不能被修改,神圣不可侵犯(前提是功能是完整无误的,修复bug不算破坏封闭性原则);

内聚性/耦合性

内聚性:表示单个模块内功能性强度性的度量;若一个模块各个元素之间联系很强,那么该模块就具有高内聚,相反就是低内聚;

耦合性:表示各个模块之间联系性的度量;若各个模块联系性很强,那么各个模块的耦合性很高,相反就是低耦合;

总结:一个好的程序架构,一般遵循高内聚低耦合,这样就能对各模块进行扩展和复用,代码质量就比较高;

1.工厂/构造者/原型模式

工厂/构造者/原型模式的共同点在于实现封装性,达到程序的复用。提高开发效率;不同点在于实现的方式不一致;代码如下:

    /*
    *定义工厂模式
    *通过函数封装某功能代码,以达到复用
    */
    function testOne(){
        var obj={
            name:"工厂模式"
        };
        obj.setName=function(name){
            this.name=name;
        }
        return obj;
    }
    //执行函数
    testOne().setName("改变了");
    /*
    *定义构造者模式
    *学过Java的知道,每个类中都有构造函数,JavaScript不是面向对象语言
    *但是它也可以实现,并通过new关键字实例化
    */
    function testTwo(){
        this.name="构造者模式";
        this.setName=function(name){
            this.name=name;
        }
    }
    //执行
    var testObj=new testTwo();
    testObj.setName("改变了");
    /*
    *定义原型模式
    *通过原型链的形式实现功能的封装
    */
    function testTwo(){
        this.name="原型模式";
    }
    testTwo.prototype.setName=function(name){
        this.name=name;
    }
    //执行
    var testObj=new testTwo();
    testObj.setName("改变了");

2.单例模式:

保证一个类只有一个实例,在实例化类之前先判断该实例是否存在,如果存在直接引入,不存在就进行实例化类;在JavaScript中,单例模式类作为一个命名空间提供者,从全局命名空间里提供一个唯一的访问点来访问该对象;通常采用自执行匿名函数和闭包方式实现;代码如下:

/*定义单例模式*/
var single=(function(){//自执行匿名函数
    var obj=null;
    /*1.访问函数外面的变量;2.把变量保存在内存中,不让变量被回收;
    **2.特点:函数1里面套函数2,然后函数1返回函数2;
    **3.缺点:容易吃内存,性能毛病;故闭包不用就将里面的变量全部null掉
    */
    function Constructor(){ 
        //dothing~~~
    }
    return {
        testSingle:function(){
            if(obj==null){
                obj=new Constructor();
            }
            return obj;
        }
    }
})();
//执行单例模式代码
single.testSingle();

以上是单例模式的一种,具体根据需求衍生出不同的单例模式;记住单例模式的核心:一个类只能有一个实例;以上单例模式不管在什么时候都会执行一次;因为采用了自执行匿名函数。如果想在有需要的时候执行,该怎么做?
惰性单例模式

    var signle=function(funs){
        var obj=null;
        return function(){
                return obj || (obj=funs.apply(this,arguments));
            }
    }

3.代理模式

“代理”生产商和消费者之间有个代理商,用来联系生产商和消费者的联系,进行商品交易。代理商要有生产商所提供的的信息展示给消费者(程序中称为接口);

  1. 真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。
  2. 代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。

代理模式的一个好处就是对外部提供统一的接口方法,而代理类在接口中实现对真实类的附加操作行为,从而可以在不影响外部调用情况下,进行系统扩展。也就是说,我要修改真实角色的操作的时候,尽量不要修改他,而是在外部在“包”一层进行附加行为,即代理类。

    var factory_obj={//定义真实对象
        name:"test",
        address:"中国北京",
        setName:function(name){
            this.name=name;
        },
        showName:function(){
            return this.name
        },
        setAddress:function(addr){
            this.address=addr;
        },
        showAddress:function(){
            return this.address;
        }
    };
    var agent_obj={//定义代理对象
        setName:function(name){
            factory_obj.setName(name);
        },
        showName:function(){
            return factory_obj.name;
        },
        setAddress:function(addr){
            factory_obj.setAddress(addr);
        },
        showAddress:function(){
            return factory_obj.address;
        }
    }
    //定义使用者
    //通过调用代理对象agent_obj来执行factory_obj对象
    agent_obj.setName("我是消费者1");
    console.log(agent_obj.showName());
    agent_obj.setAddress("江西上饶");
    console.log(agent_obj.address);

总结:在代理模式中一定要同时具备真实对象和代理对象,真实对象是实际需要操作的对象,代理对象是一个能访问到真实对象的接口。他们相互依赖;

优点:可以在不影响真实对象的基础上进行其他功能扩展;保持真实对象的完整性,符合开放封闭原则;在以上代码进行功能扩展:

    //扩展age属性,并定义setAge和showAge方法
    agent_obj['age']="16";
    agent_obj['setAge']=function(age){
        this.age=age;
    }
    age_obj['showAge']=function(){
        return this.age;
    }

4.发布/订阅者模式

发布/订阅者模式主要是为了松散耦合,提高代码质量;它大致拥有“发布者”和“订阅者”这两个角色;订阅者关注了某发布者后,当发布者发布最新状态,则订阅就会收到通知,并作出相应的动作;

场景实例:现在文章类APP都有对文章作者进行关注的功能,关注之后,当文章作者发布新文章时,系统就会通知你文章更新了。

    (function(){
        var manageObj={}; //注册管理中心
        var Publish=function(){//注册发布者
            
        }
        var Subscribe=function(){//注册订阅者
            return this;
        }
        /**
        * 注册订阅事件
        * @param type:string 订阅的标识
        * @param funs:function 订阅标识的回调函数
        **/
        Subscribe.prototype.add=function(type,funs){
            if(typeof type == "string"){
                manageObj[type]=funs;
            }else{
                console.error("add(type:string,funs:function)参数类型Error");
            }
        }
        /**
        * 取消订阅事件
        * @param type:string 订阅的标识
        **/
        Subscribe.prototype.remove=function(type){
            if(typeof type == "string"){
                var keys=Object.keys(manageObj);
                for(var i=0;i=keys.length;i++){
                    if(keys[i] == type){
                        delete manageObj[types];
                        break;
                    }
                }
            }else{
                console.error("remove(type:string)参数类型Error");
            }
        }
        /**
        * 触发订阅事件
        * @param type:string 订阅的标识
        **/
        Subscribe.prototype.trigger=function(type){
            if(typeof type == "string"){
                if(typeof manageObj[type] == "undefined"){
                    console.error(type+"没有订阅事件");
                }else{
                    manageObj[type]();
                }
            }else{
                console.error("trigger(type:string)参数类型Error");
            }
        }
        //实例化Subscribe
        var subObj=new Subscribe();
        subObj.add("definedEvent",function(){
            console.log("我是自定义事件");
        });
        subObj.trigger("definedEvent");
    })();

相关文章

网友评论

      本文标题:JavaScript常用设计模式

      本文链接:https://www.haomeiwen.com/subject/fjuqwqtx.html