外观模式、代理模式、适配器模式和装饰器模式之间有什么区别?

177

什么是 外观代理适配器装饰者 设计模式的区别?

从通用角度来看,这些模式似乎做的事情相同,即: 封装API并提供访问

如何区分这些模式?
何时选择某个模式比其他模式更合适?


https://dev59.com/p2Ml5IYBdhLWcg3wMUaP - gavenkoa
1
@gavenkoa 另一个问题只涉及代理和装饰器。 - user310291
7
有些封闭式问题竟然会显示出它们的实用性。 - Luke
2个回答

336
适配器(Adapter)将给定的类/对象适配到新接口。对于前者,通常采用多重继承。对于后者,对象被符合适配器对象包装并传递。我们要解决的问题是“不兼容接口”。
外观(Facade)更像是一个复杂功能的简单网关。您为客户端制作一个黑盒子,让它们不用担心,即“使接口更简单”。
代理(Proxy)提供与代理类相同的接口,并通常自己进行一些管理工作。 (因此,您不需要制作重型物体X的多个副本,而是制作轻量级代理P的副本,该代理管理X并根据需要转换您的调用。)您正在解决客户端不必“管理重型和/或复杂对象”的问题。
装饰器(Decorator)用于为您的对象增加更多功能(请注意术语对象 - 您通常在运行时动态装饰对象)。您不会隐藏/损害对象的现有接口,而只是在运行时“简单地扩展”它。
既然涉及到装饰器,您可能想知道为什么强调术语对象 - 一些语言(如Java)根本不允许虚拟继承(即C++所做的多重继承)以使您能够在编译时完成此操作。
由于我们引入了多重继承(以及可怕的钻石形问题),因此您需要寻找“混合” - 这是“有序线性链接接口”的解决方案,以避免多重继承的问题。但是,混合效果并不好。然后我们得到了特征(Traits) - 是的,那些在C ++模板参数中经常出现的“无状态小行为块”,它们试图以优雅方式解决行为的组合和分解问题,而不是使用多重继承或有序链接。

1
谢谢!我尽量详细地表述了,但又避免过于模糊。请原谅我无法做得更好。我已经阅读了有关特征的博士论文,但我的知识仍然相对有限,无法涵盖此领域中的所有模式 ;) - dirkgently
你预料到了一个关于mixins和traits的未来问题,但我还没有看到它们! - user310291
1
第一种设计模式(装饰器模式)与另外两种设计模式(适配器模式和代理模式)有很大的不同。以下是一个很好的比较链接(通过维基百科):NetObjectives - Liviu
@Liviu,你的链接已经失效了。我猜你最初是想指向这里(http://www.netobjectives.com/resources/net-objectives-pattern-repository),但现在似乎需要登录才能查看内容。 - Jonathan H
@Sheljohn 链接已更新 :p : 以下是第一、二、三个设计模式的良好比较链接(装饰器模式相当不同)NetObjectives(检索文本,参见“betweem”:“我在课堂上经常收到的一个问题是‘适配器、代理和外观之间有什么区别?它们看起来真的很相似’。”) - Liviu

19

外观模式(Facade)

例如,您可以使用外观模式使调用API更加容易。在这个“远程外观”示例中,从客户端隐藏了服务器上的代码实现。客户端调用一个API方法,而该方法又可以在服务器上调用1个或多个API。

适配器模式(Adapter)

这里有一个很好的例子,可以在维基百科的这里找到。客户端对象 Source 希望调用另一个对象 Target 上的方法,但另一个对象的接口与客户端期望的不同。

这时候就需要适配器对象。

它可以接收来自 Source 对象的调用,并在幕后调用应该使用的 Target 方法。

Source->CallMethodAOnTarget() ---< Adaptor.CallMethodAOnTarget() this calls ---> Target.MethodWithDifferentSignatureAndName(int i)

至于代理模式,我没有任何经验。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接