js中的设计模式

来源:互联网 发布:淘宝网商城女童鞋 编辑:程序博客网 时间:2024/05/29 15:45

讲设计模式之前,先熟悉一下软件开发的七大原则:

  1. 开-闭原则(OCP):

    一个软件实体应当对扩展开发,对修改关闭,也就是说在不改变原来的代码之上,可以对已有的模块进行扩展。

  2. 里氏替换原则(LSP):

    直观的说就是基类适用的地方都适用于他的子类。

  3. 依赖倒置原则(DIP):

    抽象不应当依赖于细节,细节应当依赖于抽象

  4. 接口隔离原则(ISP):

    一个类对另外一个类的依赖是建立在最小的接口上。

  5. 聚合复用原则(CARP):

    要尽量的使用聚合,而不是继承。

  6. 迪米特法则(LoD):

    也叫最少知识原则。一个对象应当对其他对象有尽可能少的了了解

  7. 单一职责原则(SRP):

    对于一个类而言,应当只有一个引起他变化的原因,也就是使一个类具有一个职责,把多余的职责分离出去。

软件开发中,无论是什么模式什么原则他们的目的都是为了保证系统的可靠性,健壮性,可修改性,容易理解,程序简便,效率性,先进性,可扩展性等利于后期持续开发和维护的优势。(哈哈哈,我呢就想做一个更像程序员的程序员,追求代码的可维护性是我的目前的大目标)。

我看了《javascript设计模式与开发实战》,我觉得这本书前面关于闭包,call和apply的应用,缓存以及高阶函数等部分特别好,后面的正式将的设计模式也不错,不过在熟悉前面的部分再看看后面的设计模式你会发现都是对前面的应用。

javascript这种弱类型语言并不像C++/Java这种强类型的语言一样,它弱化了类型,在使用设计模式上并不需要刻意的去仿照强类型的语言使用类型一样。

发布-订阅模式

发布订阅模式在Javascript中常用与异步编程中,在许多的框架中都是一种几乎是必备的使用模式之一,比如jQuery中的callback模块,Vue中的双向绑定部分。

所谓发布订阅,当消息发布时,订阅了这个消息的对象会得到这个通知并作出相应的行为。在javascript中主要利用缓存实现,我们可以把订阅者的行为放在一个缓存数组中,当消息发布时,将数组中的函数取出并执行,这就实现了一个简单的发布订阅,如下:

var Event={    eventqueue:[],    listener:function(key,fn){        if(!this.eventqueue[key]){            this.eventqueue[key]=[];        }        this.eventqueue[key].push(fn);    },    trigger:function(key){        var key=[].prototype.shift.call(arguments),            fns=this.eventqueue[key];        if(fns||fns.length===0){            return false;        }        for(var i=0;i<fns.length;i++){            fns[i].apply(this,arguments);        }    }}

订阅者通过listener可以订阅自己感兴趣的消息,trigger给消息发布者使用,当发布相应的信息时,订阅者收到消息并做出相应的反应。

我看过jQuery源码对callback部分的实现,源码里面有对callback设置参数实现不同的发布订阅,比如订阅一次once时,会清空相应的缓存队列,memory时会有一个参数保存着上一次的状态,执行时会使用上次的这个状态值,unique时保证向缓存数组中插入的事件唯一,总的来说虽然发布订阅代码简单的实现如上,但稍稍变形和应用就能出现一些很方便的功能,在许多许多的框架中都应用着,特实用。

装饰者模式

装饰者模式呢就是要做到不改变源代码的基础上实现对对象功能的扩展,也就是一种开闭原则的实现,强类型语言的装饰者模式的实现可能是创建一个新的类,这个类里面组合一个需要装饰的类的对象,然后这个类再扩展一些新的方法。在Javascript中呢,完全没有必要这样做,扩展一个方法时,我们可以保留对原来方法的引用,然后重写这个方法。

window.onload=function(){    alert(1);}var _a=window.onload;window.onload=function(){    _a();    alert(2);}

上面我们的实现并没有去改变原来写好的函数,只是增加了代码重写了以前的这个函数。缺点就是增加了一个中间变量,如果装饰多了,那么中间的变量也多啦,并不好。

下面讲一种用AOP实现的装饰函数

AOP(面向切面的编程)

它的主要作用是:把一些跟核心业务逻辑模块无关的功能抽离出来,再通过“动态植入”的方式参入业务逻辑模块中。这样的好处是保持了业务逻辑模块的纯净和高内聚性,其次可以方便的使用其他的功能。这些与逻辑业务无关的功能常包括日志统计,安全控制,异常处理等。

Javasript中实现AOP,都是把一个函数“动态植入”到另一个函数之中,例如下面这个例子:

Function.prototype.before=function(beforefn){    var _self=this;    return function(){        beforefn.apply(this,arguments);        return _self.apply(this,arguments);    }};Function.prototype.after=function(afterfn){    var _self=this;    return function(){        var ret=_self.apply(this,arguments);        afterfn.apply(this,arguments);        return ret;    }};var func=function(){    console.log(2);};func=func.before(function(){    console.log(1);}).after(function(){    console.log(3);});func();//结果输出://1//2//3

可以看出,这种AOP的实现其实就是将上一个待执行的对象包裹在下一个装饰对象中,最后返回包装好的待执行的对象。一层一层的包装形成了一条包装链,包装连越长对函数执行的性能会有影响,开发时也要注意不要使用过长的包装。

策略模式

我觉着策略模式在javascript中是天然存在可用的,并不需要怎么去设计,策略模式简单的说就是有多种策略,条件不同会使用不同的策略,这种关系呢,可能用很多个条件分支,使用if-else或者switch去实现,强类型语言实现或许比较麻烦,但是在javascript中呢,一个对象或则数组就搞定啦,他可以消除许多许多的条件分支,代码简单易于维护。

var strategies={    "S":function(){        alert(1);    },    "A":function(){        alert(2);    },    "B":function(){        alert(3);    }}strategies["S"](); //使用策略S

更多设计模式,推荐阅读《javascript设计模式与开发实战》

0 0
原创粉丝点击