Facade、Proxy、Adapter和Decorator设计模式有什么区别?
从通用的角度来看,这样的模式似乎在做同样的事情,那就是:包装一个 API 并提供对它的访问。
如何区分这些模式?
如何辨别一种模式何时比其他模式更适合?
Facade、Proxy、Adapter和Decorator设计模式有什么区别?
从通用的角度来看,这样的模式似乎在做同样的事情,那就是:包装一个 API 并提供对它的访问。
如何区分这些模式?
如何辨别一种模式何时比其他模式更适合?
适配器使给定的类/对象适应新的接口。在前者的情况下,通常采用多重继承。在后一种情况下,对象由符合要求的适配器对象包装并传递。我们这里要解决的问题是接口不兼容的问题。
Facade更像是通向一组复杂功能的简单网关。您为您的客户制作了一个黑匣子,让您减少担心,即使界面更简单。
Proxy提供与被代理类相同的接口,并且通常自己做一些内务处理。(因此,您无需制作重对象的多个副本,而是制作X
轻量级代理的副本,P
然后根据需要管理X
和翻译您的调用。)您正在解决客户端必须管理重和/或复杂对象的问题。
装饰器用于向您的对象添加更多火药(注意术语对象——您通常在运行时动态地装饰对象)。您不会隐藏/损害对象的现有接口,而只是在运行时对其进行扩展。
现在您已经涉及到装饰器,您可能想知道为什么要强调对象这个词——某些语言(如 Java)根本不允许虚拟继承(即 C++ 那样的多重继承)来允许您在编译时间。
由于我们已经引入了多重继承(以及可怕的菱形),您将寻找mixin——它们是接口的有序线性链接,以解决多重继承的问题。但是,mixin 并不能很好地混合。我们最终得到了特征——是的,你在 C++ 的模板参数中看到的那些无状态的小行为。Traits 试图以优雅的方式解决行为的组合和分解问题,而不是用于多重继承或有序链接。
正面
例如,您可以使用外观来更轻松地调用 API。看看这个远程门面的例子。这里的想法是服务器上代码的完整实现对客户端是隐藏的。客户端调用 1 个 API 方法,该方法又可以在服务器上进行 1 个或多个 API 调用。
适配器
可以在 Wikipedia 上找到一个很好的例子。一个客户对象Source
想调用另一个对象的方法Target
,但是另一个对象的接口与客户所期望的不同。
输入适配器对象。
它可以从Source
对象中获取调用,并在幕后调用Target
应该使用的方法。
Source->CallMethodAOnTarget() ---< Adaptor.CallMethodAOnTarget() this calls ---> Target.MethodWithDifferentSignatureAndName(int i)
至于代理,我对这种设计模式没有任何经验。