我读过装饰器对客户端比适配器更透明,正是这种透明度使嵌套装饰成为可能。在这种情况下,透明度实际上意味着什么?
PS:我知道这两种设计模式。所以你可以在这个前提下做出你的答案。
我读过装饰器对客户端比适配器更透明,正是这种透明度使嵌套装饰成为可能。在这种情况下,透明度实际上意味着什么?
PS:我知道这两种设计模式。所以你可以在这个前提下做出你的答案。
装饰器获取给定类型 A 的对象,并将其包装到相同类型 A 的对象中。客户端可以像使用实际对象一样使用装饰对象,因为它们具有相同的类型。
适配器获取给定类型 A 的对象,并将其包装到另一个类型 B 的对象中。使用原始类型 A 的客户端必须适应使用另一个类型 B。
也就是说,如果我们使用适配器模式,正是因为客户端需要 B 类型的对象,而我们只有 A 类型的对象。所以我们将它包装到适配器中,使其成为 B 类型的对象。
这两种模式使用相同的原理(包装),但目的不同。一个装饰器来改变原始对象的行为。用于更改其类型的适配器。
客户端使用装饰器和装饰对象没有区别(两者具有相同的接口)。因此装饰器是透明的(即对客户端不可见)。装饰器也可以被其他装饰器装饰——不会影响客户端。客户仍然可以认为他正在使用装饰对象。
很好的样本是Streams
。您可以传递用任意数量的装饰器(压缩、加密、缓冲)装饰的流,但这些装饰器对于任何使用流的客户端都将保持不可见。
其实我不明白为什么适配器可以被认为是透明的。客户端不应该知道适配器的类型,并且客户端不能将适配器视为适配器,因为它们具有不同的接口。
回答装饰器是如何透明的比为什么适配器偷偷摸摸或笨拙更直接。装饰器往往更频繁地嵌套到大量功能(这通常是正交的,例如 BufferedFileWriter 添加了缓冲,这并没有真正改变其包装类的基本操作:它将那些委托回原来的)。通常,您可以很容易地看到装饰器在做什么,因为它在原始界面中隐藏了自己。
适配器可以同样透明。我猜想嵌套适配器更困难的原因是您正在谈论转换某些状态对象。然后你很快就会了解所有隐含的丑陋(随着 MVC 的发展而发生的事情之一)。例如,我有一个旧应用程序,它会给我一个风险评级,给我一堆输入。有一个新的 Web 界面想要使用它,但它需要另一种格式的数据。我们无法更改原始代码,因此我们引入了一个可以翻译的适配器。它在翻译什么?一般有一些状态表示。因此,如果接口不同,它将接受输入并转换和重新调整它们,如果输出需要进一步按摩,同上。如果您将多个适配器分层,
装饰器通常不用于此类翻译工作,而是用于补充我们没有代码的东西的功能,或者再次,新功能是正交的,因此,我们允许用户使用或者不使用一个或多个装饰器。