首页 > 代码库 > Javascript 部分设计模式的个人理解

Javascript 部分设计模式的个人理解

9 单例模式(确保自己使用的资源都是全局的)

1)普通单体(字面量初始化对象)

var person = {
name : ‘zhangsan‘,
age : 12,
getAge : function(){
return this.age ;
}
}
person.height = 185 ;

这种单体在实际开发中常用在两个地方,其一就是 匿名对象,其二就是 划分命名空间!

2 )具有局部变量的单体(动态加载数据,初始化属性,返回一个对象实例)

 var UserInfo = (function(){           //同闭包的原
  var name = "";         //利用闭包是单体有自己的私有局部变量
  var code = "";
  Ajax.request("url",function(n,c){
   name = n;
   code = c;
  })
  return {
   name:name,
   code:code
  }
 })()

3)惰性单体(用一个私有变量代替第二种方法返回的实例)

var UserInfo = (function(){
  var userInfo = "";      //私有变量
  function init(){        //利用闭包是单体有自己的私有局部变量 
   var name = "";
   var code = "";
   Ajax.request("url",function(n,c){ 
    name = n;
    code = c;
   })
   return {
    name:name,
    code:code
 } 
  }
  return {
   getInstance : function(){
    if(userInfo){
     return userInfo;
    }else{
     userInfo = init();
     return userInfo;
    }
   }
  }
 })()

4 ) 分支单体(这种方法就是通过判断返回一个什么样的实例,也就是分支,是上面方法的结合使用)


10 工厂模式

1)简单工厂(简单的说就是一个接口以及他的多个实现类,通过一个单例工厂类来根据客户的需求new 出对应接口实现类的对象,这种方式其实就是类似于java里面的静态工厂模式,没有多大意义。原因就是没有动态效果,如果新增一个实现类又要改变if语句,又要修改工厂类的源码,没意义!)

2)工厂模式(他与工厂模式的区别就在于它是给人误解为动态的,他的整个个原理是这样的:在简单工厂模式的基础下,把工厂类定义为抽象类,那么具体工厂类的实现类就是我们通过使用if语句来判断new出什么对象的一个类,那么它会根据不同的情况有各种各样的工厂实现类,那么接口有新的实现类时没必要改变所有的工厂实现类,只需改变其中需要的那个就可以了,所以这也不是动态的)


11 桥梁模式

    1)目的:将抽象类与其实现类隔离开来,以便二者独立开来,互不干扰的开发!

    2)思想:比如我们任意写一个了服务类,很多客户端都要调用这个类的服务,那么我就可以在客户端与服务类之间新建一个桥梁,用来处理二者的相互调用,这样就能把二者分离开来!当然这个确实有点类似于门面模式或适配器模式,然而意义是不一样的。

        A 对于适配器模式来说:他的目的是在服务类并不能直接被客户端所用(不兼容)的情况下,要在中间设置一个适配器来改造服务类的调用,但又不修改服务类本身。

        B 对于桥梁模式来说:他的目的是在客户端调用服务类时,用一个桥梁把二者隔离开来,从而达到二者互不干扰的目的。而且桥梁模式还有一个很重要的作用就是在桥梁中能够处理多个不同服务类的之间的相互调用!

        C 对于门面模式来说:他的目的是为服务类创建一个中间便利类,把复杂接口改造成一个简单易用的接口,他与以上两种设计模式的差异就在于门面模式并不是强调服务类被某个或某些特定的客户端容易调用,而是为服务类编写一个容易被调用的接口门面类。所以,对于浏览器不兼容的服务类我们就应该使用门面模式来封装,比如事件注册,XMLHttpRequest封装


12 门面模式

    1)作用:简化类的接口,同时消除服务类与使用它的客户端之间的耦合,还能够完成与与桥接模式类似的功能就是多个类的相互调用在门面类中。

    2)思想:比如我们写了一个服务类,他的接口很复杂,然而我们就可以为这个服务类创建一个门面类,这个门面类的目的就是为了简化服务类接口的调用。这里完全没有牵连到客户端的东西,原因就是门面模式是为服务类服务的,适配器模式是为了服务类与客户端兼容的,桥梁模式是为了服务类与客户类分离的。

    3)所谓的一些封装或者脚本库如Jquery等都是采用门面模式的原理。


13 适配器模式

    1)概念:适配器模式可用来在现有接口和不兼容的类之间进行适配,其实也就是包装模式,因为是在用一个新的接口包装成另一个对象,许多情况下,许多服务类接口并不能直接被客户端所使用,这时我们借助于适配器模式,你不用直接修改这些服务类,而是借助一个适配器来改造他的接口,从而达到客户端的可调用性。

    2)适配器模式很想买门面模式,他们都要对别的对象进行包装并改变其呈现的接口,二者的差异在于:他们是如何改变接口的,门面模式展现的是一个简化的接口,他并不提供额外的选择,而且有时为了方便完成常见的任务他还会做出一些假设。适配器则要把一个接口转换为另一个接口,他并不会滤除某些能力,也不会简化接口,如果客户系统期待的API不可用,那就需要用到适配器。


14 组合模式

    1)一种专为创建Web上的动态用户界面而量身定制模式,使用这种模式,可以用一条命令在多个对象上激发复杂的或递归的行为。

    2)思想:就是类似于文件夹,一个组合类中有组合类同时还会有叶子类,这种模式我个人觉得用在的场合和特殊,只能是这种包含于被包含而且是在叶子节点和组合节点有相同特征的情况下使用。所以我们的组合类和叶子类都必须实现相同的接口,而且组合类中应该保存叶子类的引用和组合类的引用。


15 装饰模式

    1)概念:可用来透明的把对象包装在具有同样接口的另一对象之中,通过在另一个对象中添加对应的实现功能完成原始对象的装饰。目的就是减少子类。

    2)思想:对于一个服务类,需要在这个服务类的某个接口上新增一些功能,而且服务类是不能修改的,那么我们可能会选择新建一个子类来重写这个方法,这样当然可以实现,但是如果对每添加一个功能都要创建一个新类的话,会产生大量的子类,所以就有装饰模式,装饰类与服务类实现同一个接口,而且装饰类里面具有服务类的引用,所谓装饰就是在装饰类重写方法的时候调用了服务类的同名方法,于此同时还添加了自己的功能。

    3)对比:代理模式也是在为服务类的某个接口改变一些功能,注意是改变不一定就是新增功能,所以这就是代理模式的本质区别,装饰模式是说在调用服务类的方法同时能够新增一些功能,那么在装饰模式中服务类的接口是一定会被调用的,然而代理模式则不是,使不使用服务类的接口那是代理类本身来决定的。但是代理模式和装饰模式的实现几乎相同,因为代理模式也是这样实现的,代理类与被代理类都实现了相同的接口,同时代理类中有被代理类的引用。

    4)对比:装饰模式和组合模式之间有许多共同点,装饰者对象和组合对象都是用来包装别的对象,他们都与所包装的对象实现同样的接口并且会把任何方法调用传递给这些对象。组合模式是一种结构模式,用于把众多子对象组织为一个整体,当程序员与大批对象打交道时可以将他们当做一个对象来对待,并将他们组织为层次性的树。通常他们并不修改方法调用,而只是将其沿组合对象与子对象的链向下传递,直到到达被落实在叶对象上。装饰模式也是一种结构模式,他并非用于组织对象,而是用于在不修改现有对象或从其派生子类的前提下为其增添职责,创建装饰者的目的就在于对方法进行修改。

    5)扩展:如果你觉得装饰模式就只是改变方法那点功能的话,那你就太肤浅了,原因是我们还可以在装饰类中新增一些接口之外的方法,那么这些方法就是新增的功能,这个就是java中IO使用的装饰模式。


16 代理模式

    1)概念:代理模式最基本的形式是对访问进行控制,代理对象和被代理对象实现同一个接口,客户端只与代理对象打交道,调用的是代理对象的接口,然而实际上工作的是被代理对象(本体)工作,本体才是负责执行所分派的任务那个对象。代理对象所做的不外乎控制本体的访问,注意:代理对象并不会在另一个对象的基础上添加方法或修改其方法(这是与装饰模式的区别),也不会简化那个对象的接口(这是与门面模式的区别)。代理对象与本体实现同一个接口,客户端对代理的调用都会被传到本体对应的接口中。

    2)分类:虚拟代理,远程代理,保护代理

            A 虚拟代理:代理模式一开始是把本体实例化放在代理对象实例化的同时实例的(代理类的构造函数中实例化本体对象),如果使用虚拟代理的话就是在实现接口的所有方法中做一个判断,如果本体对象为空的就实例。也就是说吧本体实例化的过程放在了等需要调用到本体时才实例化。

            B 远程代理:用户访问另一个环境中的对象,javascript中很少使用或实现。

            C 保护代理:根据用户身份来控制代理对本体的访问,这个在javascript中很难做到,一般是在java中实现。

    3)对比:

                    


17 亨元模式

    1)概念:亨元模式用于减少应用程序所需要对象的数量,这是通过将对象的内部状态划分为内在数据和外在数据两类实现的。内在数据是指类的内部方法所需要的信息,没有这种数据的话类就不能正常运作,换句话说内部数据就是这个类必须拥有的属性,所以所有的对象基本上都拥有这些属性,而且属性的值也都是固定的那么一些值,从而我们可以把这些值分别创建对象用来外部共享,也就是享元对象。外在数据则是可以从类身上剥离并存储在其外部的信息,换句话说外部信息其实是这个对象并不是很紧密的一些属性,但同时却是这个对象独一无二用以区别其他对象的属性。

    2)思想:将内在状态相同的所有对象替换为同一个共享对象,外在状态的属性是不可能相同的,所以就是用以区分对象的,因此外在状态必须作为某些信息被封装。因为内在状态对象被共享所以使用工厂模式来控制对象的生成。形象的例子就是:一盘围棋的所有棋子:把棋子的颜色作为内在属性,所以只可能有两个对象黑和白,然后把对象的位置作为外部属性,那就是唯一的,可以用参数保存也可以从新定义对象。

    3)作用:就是减少对象,其实很复杂。

    4)总结:在java中有一个抽象的亨元角色(定义了共享对象的所有接口),有多个具体的亨元角色(实现抽象亨元角色,同时定义自己的方法),有一个工厂类(根据外部判断内存中是否已经实例化过具体共享的亨元角色对象,如果有就不实例化直接返回,否则实例化在返回)。


18 命令模式

    1)概念:一般情况下,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”,也就是发送命令和执行命令都是封装在一处完成。但在某些场合,如何将“行为请求者”与“行为实现者”解耦?将一组行为抽象为对象,同时将一组实现也抽象为对象,达到实现二者之间的松耦合关系。

    2)思想:首先我们要定义一个抽象接口,他就是抽象命令角色,它定义了命令的基本操作,其次就是具体命令角色,我们把具体的命令抽象为一个类,这个类通过实现接口中的方法来完成命令的处理,说道命令的处理自然不是具体命令类所要做的事情,那么命令类中应该有处理命令对象的引用,那个对象就是接收者,接收者应该也要实现抽象命令角色,这样就类似于代理模式的调用。那么命令的生成又是谁来呢,那就是客户端,客户端发送一个命令(初始化一个命令对象),然后调用发送给Invoker(命令调用)对象,自然客户端要把所创建的命令对象一同给命令调用者,那么命令调用者拥有命令对象的引用,在内部调用命令对象的方法,从而就执行了整个命令的完成。

    3)流程:客户端 -----》发出命令(初始化命令对象)----》传递给Invoker------》Invoker调用命令-------》命令调用行为实现者----》处理。

    4)个人理解:这个不就是一个代理模式吗,只是相对代理而言,命令角色有种层层传递到最底层的感觉罢了。


19 观察者模式

    1)概念:一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。此种模式通常被用来实现事件处理系统。

    2)思想:首先我们定义一个观察者接口,声明观察者共有的方法。然后我们就可以编写具体观察者角色实现抽象接口。这边就是被观察者,他也是一个抽象接口,声明诸多与观察者相关的方法,比如撤销观察者,注册观察者等,然后同样编写具体的被观察者实现抽象接口,最重要的是被观察者中有一个抽象观察者的集合引用,用来存放已经注册的观察者,一旦有事情通知观察者就只需遍历集合然后调用观察者对象的方法处理。

    3)javascript中的例子就是事件处理器(一个被观察者只有一个观察者)与事件监听器(一个被观察者可以拥有多个观察者),他们都是观察者模式。


20 责任链模式

    1)概念:用来消除请求的发送者和接收者之间的耦合,这是通过实现一个由隐式的请求进行处理的对象组成的链而做到的。链中每个对象可以处理请求,也可以将其传给下一个对象

    2)思想:一个简单的客户类就是请求的发送者,发送者的任务就是创建命令或说发出请求;其次就是接收者或者说是一个命令的处理者(链子),他就是核心,那么我们首先声明一个抽象接口,定义链子的共有的方法,然后所有的链子实现这个接口中的方法,并且每个链子都有一个该接口类型的引用,用来存放下一个链子的对象。那么命令处理就是这样的,客户端创建了一个命令,然后发送出这个命令,之后就是由链子处理,如果开头的链子能够处理那么我就返回结果给客户端,如果不能处理命令那就把命令继续传递给下一个链子,让下一个处理,直到处理完成。

    3)对比:命令模式其实也是这样的一个流程,唯一二者的差异就在于处理,命令模式一直是把命令发送给最底层的来处理,然而责任链则不是,他是只要有一个链子能够处理命令就可以不用执行下面的流程了。

    4)例子:javascript 中的冒泡模型就是这个原理,还有一个很突出的就是拦截器,tomcat中设置的拦截器filter就是这个原理,使用chain.doFilter();执行下一个拦截器,否则直接热return。


Javascript 部分设计模式的个人理解