/design-pattern

设计模式相关

Primary LanguageJavaScriptMIT LicenseMIT

《 javascript 设计模式 》 读书笔记

鸭式辩型

类是否声明自己支持哪些接口并不重要,只要它具有这些接口中的方法就行,(像鸭子一样走路并且嘎嘎叫的就是鸭子),鸭式辩型正式基于这样的认识,他把对象实现的方法及作为判断他是不是某个类的实例的唯一标准,这种技术在检查一个类是否实现了某个接口时也可以大显身手,这种方法的背后的观点很简单:如果对象具有与接口定义的方法同名的所有方法,那么就可以认为他实现了这个接口。

工厂模式

把成员对象的创建工作转交给一个外部对象。这个外部对象可以是一个简单的命名空间,也可以是一个类的实例。如果负责创建实例的方法的逻辑不会发生变化,那么一般来说用单体或者静态类方法创建这些成员实例是合乎情理的。 真正的工厂模式与简单工厂模式的区别在于,它是不是使用一个类或对象来创建实例的,而是使用一个子类,按照正式定义,工厂是一个将其成员对象的实例化推迟到子类中进行的类。 工厂模式的适用场合:

  1. 动态实现
  2. 节省设置开销
  3. 用许多小型对象组成一个大对象

桥接模式:将抽象与其实现隔离开来,以便二者独立变化;如果一个桥接函数被用于链接两个函数,而其中的某个函数根本不会在桥接函数之外被调用,那么此时这个桥接函数就不是非要不可,你可以放心的将他删除。

组合模式

组合模式是一种专为创建web上的动态用户界面而量身制作的模式,使用这种模式可以用一条命令在多个对象上激发复杂的或者递归的行为。这可以简化粘和性代码,使其更容易维护,而那些复杂行为则被委托给各个对象。两个好处: 你可以用同样的方法处理对象的集合与其中的特定的子对象。 它可以用来把一批子对象组织成树形结构。 如:在设计表单校验时,可以将一个完整的Form分成多个fieldSet,然后对每个fieldSet增加validate()方法,在最终的保存校验时,只需要遍历每个fieldSet的validate()方法就可以得到完整的校验结果。

门面模式

门面模式有两个作用:一是简化类的接口;二是消除类与使用他的客户代码之间的耦合。在JS中,它几乎是所有JS库的核心原则,通过创建一些遍历方法让复杂系统变得更加简单易用。 其实,门面模式就是对同类复杂代码的封装,使其调用起来更方便,而不用关注不同的复杂情况下的差异性判断。 门面模式的另一个好处表现在对函数的组合上,这些组合而得的函数又叫便利函数,此处可以联想到函数柯里化或者redux的内部实现上。 可能存在的弊端:有时执行一个比较庞杂的门面函数,其组成的函数在力度方面更有吸引力,这是因为门面函数可能常常会执行一些并不需要的任务。这就需要在门面函数时,尽可能的负责单一职责原则,从而减低函数间的耦合。也可以通过门面模式间的嵌套还解决。

适配器模式

适配器模式可用来在现有接口和不兼容的类之间进行适配。适用这种模式的对象也叫包装器(wrapper),因为它们是在用一个新的接口包装另一个对象。 适配器可以被添加到现有代码中以协调两个不同的接口,如果现有代码的接口能很好的满足需要,那就可能没有必要适用适配器。但要是现有接口对于手头的工作来说不够直观或者适用,那么可以使用适配器来提供一个更简洁或更丰富(option-rich)的接口。 从表面上看,适配器模式很像门面模式,他们都要对别的对象进行包装并改变其呈现的接口。二者的差别在于他们如何改变接口。、门面元素展现的是一个简化的接口,它并不提供额外的选择,而且有时为了方便完成常见任务他还会做出一些假定。而适配器则要把一个接口转换成另一个接口,他并不会滤除某些能力,也不会简化接口。如果客户系统期待的API不可用,那就需要用到适配器。 适配器可被实现为不兼容的方法调用之间的一个代码薄层。

装饰者模式

装饰者模式(decorator pattern)可以用来透明的把对象包装在具有同样接口的另一个对象之中。这样一来,你可以给一个方法添加一些行为,然后将方法调用传递给原始对象。相对于创建子类来说,使用装饰者对象是一种更灵活的选择。

组合模式与装饰者模式比较: 组合模式是一种结构型模式,用于把众多子对象组织成一个成立,借此程序员与大批对象打交道时可以将他们当做一个对象来对待,并将他们组织为层次性的树。通常他并不修改方法调用,而只是将其沿组合对象与子对象的链向下传递,知道到达并落实再叶对象上。 装饰者模式也是一种结构型模式,但它并非用于组织对象,而是用于在不修改现有对象或从其派生子类的前提下为其增添职责 尽管简单的组合对象可等同于简单的装饰者,这二者却有着不同的焦点。组合对象并不修改方法调用,其着眼点在于组织子对象。而装饰着存在的唯一目的就是修改方法调用而不是组织子对象,因为子对象只有一个。

装饰者模式的适用场景:

  • 如果需要为类增添特性或职责,而从该类派生子类的解决方法并不实际的话,就应该适用装饰者模式,派生自雷之所以会不实际,最常见的原因是需要增加的特性的数量和组合要求适用大量子类。

  • 如果需要为对象增添特性而又不想改变适用该对象的代码的话,可以采用装饰者模式。因为装饰者可以动态而又透明的修改对象,所以他们很适用于修改现有系统这一任务。相比卷入创建和维护子类的麻烦,创建和应用一些装饰者往往要省事的很多。

享元模式

flyweight(共享,元素)它最适用于解决因创建大量类似对象而累积性能的问题。核心是共享。 享元模式用于减少应用程序所需对象的数量。这是通过将对象的内部状态划分为内在数据和外在数据两类而实现的。内在数据是指类的内部方法所需要的信息,没有这种数据的话类就不能正常运转。外在数据则是可以从类身上剥离并存储在其外部的信息。我们可以将内在状态相同的所有对象替换为同一个共享对象,用这种方法可以把对象数量减少到不同内在状态的数量。 创建这种共享对象需要使用工厂,而不是普通的构造函数。这样做可以跟踪到已经实例化的各个对象,从而仅当所需对象的内在状态不同于已有对象时才创建一个新对象。对象的外在状态被保存在一个管理器对象中。在调用对象的方法时,管理器会把这些外在状态作为参数传入。

代理模式

代理是一个对象,它可以用来控制对另一个对象的访问,他与另外那个对象实现了同样的接口,并且会把任何方法调用传递给那个对象。另外那个对象通常称为本体(real subject)。代理可以代替其本体被实例化,并使其可以被远程访问。他还可以把本题的实例化推迟到真正需要的时候,对于实例化比较费时的本体,或者因尺寸比较大以至于不用时不宜保存在内存中的本体,这特别有用。在处理那些需要较长时间才能吧数据载入用户界面的类时,代理也大有裨益。 代理模式最基本的形式是对访问进行控制。

观察者模式

在事件驱动的环境中,比如浏览器这种持续寻求用户关注的环境中,观察者模式是一种管理人与其任务之间的关系(确切的讲,是对象及其行为和状态之间的关系)的得力工具。

命令模式

它可以用来对方法调用进行参数化处理和传送,经过这样处理过的方法调用可以在任何需要的时候执行。它也可用来消除调用操作的对象和实现操作的对象之间的耦合,这位各种具体的类的更换带来了极大的灵活性。这种模式也可以用在许多不同的场合,不过它在创建用户界面这一方面非常有用,特别是在需要不受限(unlimited)取消(undo)操作的时候,它还可以用来替代回调函数,因为他能够提高在对象之间传递的操作的模块化程度。 最简单的命令对象是一个操作和用以调用这个操作的对象的结合体。

职责链模式

他可以用来消除请求的发送者和接受者之间的耦合,这是通过实现一个由隐式的对请求进行处理的对象组成的链而做到的,链中的每个对象可以处理请求,也可以将其传给下一个对象。js内部就是用了这种模式来处理时间捕获和冒泡的问题。 职责链由多个不同类型的对象组成。发送这是发出请求的对象,接受者是链中那些接受这种请求并且对其进行处理或传递的对象,请求本身有时也是一个对象,它封装着对操作有关的所有数据。其典型的运转流程大致是: 发送者知道链中的第一个接受者,他向这个接收者发出请求; 每一个接受者都对请求进行分析,然后要么处理他,要么将其往下传递。 每一个接受者知道的其他对象只有一个,即它在链中的下家(successor); 如果没有任何接受者处理请求,那么请求将从链上离开。不同的实现对此有不同的反应,既可能无声无息,也可能抛出一个错误。 职责链模式的适用场合: 如果事先不知道在几个对象中有哪些能够处理请求,那么这就属于应该使用职责链的情况。如果这批处理器对象在开发期间不可知,而是需要动态指定的话,那么也应该使用这种模式。该模式还可以用在对于每个请求都不止有一个对象可以对他进行处理这种情况下。 使用这种模式,可以把特定的具体类与客户隔离开,并代之以一条由弱耦合的对象组成的链,他将隐式的对请求进行处理。这有助于提高代码的模块化程度和可维护性。