JavaScript设计模式笔记 - 适配器模式 装饰者模式

1、适配器模式:

适配模式可用来在现有接口和不兼容的类之间进行适配,使用这种模式的对象又叫包装器(wrapper),因为它们是在用一个新的接口包装另一个对象。

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

PS2-to-USB适配器就是一个例子。

示例:创建一个简单的适配器方法,修改传入参数的方式

示例:适配两个库

示例:适配电子邮件API

添加适配器

1.1、适配器模式的适用场合:

适配器适用于客户系统期待的接口与现有API提供的接口不兼容这种场合。适配器所适配的两个方法执行的应该是类似的任务,否则的话就解决不了问题。就像桥接元素和外观元素一样,通过创建适配器,可以把抽象与其实现隔离开来,以便二者独立变化。

1.2、适配器模式之利:

用一个新的接口对现有类的接口进行包装,这样客户程序就能使用这个并非为其量身打造的类而又无需为此大动手术。

1.3、设配器模式之弊:

有人认为适配器是一种不必要的开销,完全可以通过重写现有代码避免。此外适配器模式也会引入一批需要支持的新工具。如果现有API还未定形,或者新接口还未定形,那么适配器可能不会一直管用。

在涉及大型系统和遗留框架的情况下,它的优点往往比缺点更突出。

2、装饰者模式

实例:创建自行车的装饰者

2.1、接口在装饰者模式中的角色:

装饰者模式颇多得益于接口的使用。装饰者最重要的特点之一就是它可以用来替代其组件。

接口说明了装饰者必须实现哪些方法,有助于防止开发过程中的错误。

如果装饰者对象与其组件不能互换使用,它就丧失了其功用。这是装饰者模式的关键特点,要注意防止装饰者和组件出现的接口方法的差异。这种模式的好处之一就是可以透明的用新对象装饰现有系统中的对象,这并不会改变代码中的其他东西,只有装饰者和组件实现了同样的接口才能做到这一点。

2.2、装饰者模式与组合模式的比较:

相同点:

装饰者对象和组合对象都是用来包装别的对象(组合模式:子对象,装饰者模式:组件)

都与所包装的对象实现同样的接口并且会把任何方法调用传递给这些对象

不同点:

组合模式是一种结构型模式,用于把众多子对象组织为一个整体。通常并不需要修改方法调用,而只是将其沿组合对象与子对象的链向下传递,直到到达并落实在叶对象上。装饰者模式也是一种结构型模式,但它并非用于组织对象,而是用于在不修改现有对象或从派生子类的前提下为其增添职责。创建装饰者的目的就在于对方法进行修改,其做法是先传递方法调用,然后修改其返回结果。

组合对象不修改方法调用,着眼在于组织对象,而装饰者存在的唯一目的就是修改方法调用而不是组织子对象,因为子对象只有一个。

2.3、装饰者修改其组件的方式

在方法之后添加行为

在方法之前添加行为

替换方法

有时候为了实现新行为必须对方法进行整体替换。在此情况下,组件方法不会被调用(或虽然被调用但其返回值会被抛弃)。

添加新方法

与新方法装饰组件对象想必对现有方法进行修改更容易实施,而且更不容易出错,这是因为采用后一种做法时,被装饰的对象用起来与之前没什么不同,外围代码也就不需要修改了。

话虽如此,在装饰着中添加新方法又是也是为类增加功能的一种强有力的手段。我们可以用这种装饰者为自行车对象增添一个按铃方法。这是一个新功能,没有装饰者自行车就不可能执行这个任务。(见例子)

详细的例子:example

2.4、工厂的角色

如果必须确保按照某种特定顺序创建装饰者,那么可以为此使用工厂对象。实际上,不管顺序是否要紧,工厂都很适合于创建装饰对象。

用工厂实例化自行车对象有许多好处。首先,不必了解自行车和装饰者的各种类名,所有这些信息都封装在AcmeBicycleShop类中。因此添加自行车型号和选件非常容易,只要把它们添加到AcmeBicycleShp.models或AcmeBicycleShop.options数组中即可。

例子:AcmeBicycleShop类的createBicycle方法,以便用户可以指定自行车要配的选件。

通过上面例子最后创建带装饰的自行车对象的两种不同做法,可以发现,第一种方法与客户代码紧密耦合在一起的类不下5个,第二种方法使用了工厂,与客户代码耦合在一起的只有一个类,即那个工厂本身。

2.5、函数装饰者

装饰者并不局限于类,你也可以创建用来包装独立的函数和方法的装饰者。

example:

2.6、装饰者模式的适用场合

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

如果需要为对象添加特性而又不想改变使用该对象的代码的话,也可以采用装饰者模式。因为装饰者可以动态而又透明地修改对象,所以它们很适合于修改现有系统这一任务。

2.7、示例:方法性能分析器

本例要创建的装饰者可以用来包装任何对象以便为其提供方法性能分析功能。我们打算在每一个方法的前后添加一些代码,分别用于启动计时器和停止计时器并报告结果。

example

2.8、装饰者模式之利

装饰者是在运行期间为对象增添特性或职责的有工具。

装饰者的运行过程是透明的,这就是说你可以用它包装其他对象,然后继续按之前使用那些对象的方法来使用它。装饰者为程序员带来了极大的灵活性。

2.9、装饰者模式之弊

在遇到用装饰者包装起来的对象时,那些依赖于类型检查的代码会出问题。

使用装饰者模式往往会增加架构的复杂程度。此外,实现具有动态接口的装饰者(如MethodProfiler)涉及的语法细节有时也会令人生畏。在设计一个使用了装饰者模式的架构时,你西部多花点心思,确保自己的代码有良好的文档说明,并且容易理解。

arthinking wechat
欢迎关注itzhai公众号