我对这个主题的看法。
所有四种模式都有很多共同点,所有四种模式有时都被非正式地称为包装器或包装器模式。所有使用组合,包装主题并在某个时候将执行委托给主题,将一个方法调用映射到另一个方法调用。它们使客户不必构建不同的对象并复制所有相关数据。如果使用得当,它们可以节省内存和处理器。
通过促进松散耦合,它们使曾经稳定的代码更少暴露于不可避免的变化中,并且对于其他开发人员来说更好地可读。
适配器
适配器将主题(适配器)适配到不同的接口。通过这种方式,我们可以将对象添加到名义上不同类型的集合中。
适配器只向客户端公开相关方法,可以限制所有其他方法,揭示特定上下文的使用意图,例如调整外部库,使其看起来不那么通用,更专注于我们的应用程序需求。适配器增加了我们代码的可读性和自我描述。
适配器保护一个团队免受其他团队的易失代码的影响;与离岸团队打交道时的救星工具;-)
较少提及的目的是防止主题类过多的注释。有这么多基于注释的框架,这变得比以往任何时候都更重要。
Adapter 有助于解决 Java 对单一继承的限制。它可以将多个适配器组合在一个信封中,给人以多重继承的印象。
在代码方面,适配器很“瘦”。除了简单地调用适配器方法和进行此类调用所需的偶尔数据转换之外,它不应向适配器类添加太多代码。
JDK 或基本库中没有很多好的适配器示例。应用程序开发人员创建适配器,以使库适应应用程序特定的接口。
装饰器
装饰器不只是委托,不只是将一个方法映射到另一个,他们做的更多,他们修改一些主体方法的行为,它可以决定根本不调用主体方法,委托给不同的对象,一个辅助对象。
装饰器通常会(透明地)向包装对象添加功能,例如记录、加密、格式化或压缩到主题。这个新功能可能会带来很多新代码。因此,装饰器通常比适配器“胖”得多。
装饰器必须是主题接口的子类。它们可以透明地使用而不是其主题。请参阅 BufferedOutputStream,它仍然是 OutputStream,可以这样使用。这是与适配器的主要技术差异。
整个装饰器系列的教科书示例很容易在 JDK - Java IO 中。所有像BufferedOutputStream、FilterOutputStream和ObjectOutputStream这样的类都是OutputStream的装饰器。它们可以是洋葱层,其中一个装饰器再次装饰,增加更多功能。
代理
代理不是典型的包装器。被包装的对象,即代理主体,在创建代理时可能还不存在。代理经常在内部创建它。它可能是按需创建的重对象,也可能是不同 JVM 或不同网络节点中的远程对象,甚至是非 Java 对象,本机代码中的组件。它根本不需要包装或委托给另一个对象。
最典型的例子是远程代理、重对象初始化器和访问代理。
立面
Facade 与最少知识的设计原则(得墨忒耳法则)密切相关。
Facade 与 Adapter 非常相似。它们都包裹,它们都将一个对象映射到另一个对象,但它们的意图不同。 Facade 将复杂结构的主体、复杂对象图展平,简化了对复杂结构的访问。
Facade 封装了一个复杂的结构,为它提供了一个平面接口。这可以防止客户端对象暴露于主体结构中的内部关系,从而促进松散耦合。
桥梁
适配器模式的更复杂变体,不仅实现不同,而且抽象也不同。它为委托增加了一种间接性。额外的代表团是桥梁。它甚至将适配器与适配接口解耦。它比其他任何包装模式都增加了复杂性,因此请谨慎应用。
构造函数的区别
查看构造函数时,模式差异也很明显。
现实生活中的例子——JAXB Marshalling Adapter。这个适配器的目的是将一个简单的平面类映射到外部需要的更复杂的结构,并防止过多的注释“污染”主题类。