代理、装饰者、适配器和桥接模式有什么不同?[英] How do the Proxy, Decorator, Adapter, and Bridge Patterns differ?

本文是小编为大家收集整理的关于代理、装饰者、适配器和桥接模式有什么不同?的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我正在看代理模式,对我来说,这似乎很糟糕,就像装饰器,适配器和桥梁图案一样.我误会了什么吗?有什么不同?为什么我要使用代理模式与其他模式?您过去如何在现实世界项目中使用它们?

推荐答案

代理,装饰器,适配器和桥梁都是"包装"类的变体.但是它们的用途不同.

  • 代理可以在要懒惰的对象时使用或隐藏要调用远程服务或控制对象的访问的事实.

  • 装饰器也称为"智能代理".当您要在对象中添加功能时,而不是通过扩展该对象的类型来使用此功能.这使您可以在运行时进行.

  • 适配器在您具有抽象接口时使用,并且要将该界面映射到具有相似功能角色但不同接口的另一个对象.

  • 桥梁与适配器非常相似,但是当您同时定义抽象接口和基础实现时,我们称其为桥梁. IE.您不适合某些遗产或第三方代码,而是所有代码的设计师,但您需要能够交换不同的实现.

  • 立面是一个或多个类的子系统的更高级别(读:简单)接口.假设您有一个复杂的概念,需要代表多个对象.对该对象进行更改是令人困惑的,因为您并不总是知道哪种对象具有需要调用的方法.现在是时候编写一个立面,为您可以为对象集合提供的所有复杂操作提供高级方法.示例:学校部分的域模型,采用countStudents(),reportAttendance(),assignSubstituteTeacher()等方法.

其他推荐答案

作为比尔的答案说,他们的用例不同.

它们的结构也是如此.

  • 代理和 decorator 都具有与包装类型相同的界面,但是代理在引擎盖下创建了一个实例,而装饰器则在实例中进行了实例构造函数.

  • 适配器和立面都具有与包裹的界面不同的界面.但是适配器源自现有界面,而立面则创建了一个新的接口.

  • 桥梁和适配器两个都在现有类型上.但是桥梁将指向抽象类型,并且适配器可能指向混凝土类型.该桥将允许您在运行时配对实现,而适配器通常不会.

其他推荐答案

我对这个主题的看法.

所有四个图案都有很多共同点,有时四个模式都非正式地称为包装纸或包装器图案.所有人都使用构图,包装主题并在某个时候将执行委派给主体,请映射一个方法,将其列为另一个方法.他们避免了客户必须构建另一个对象并在所有相关数据上复制的必要性.如果明智地使用,它们可以节省内存和处理器.

通过促进松散的耦合,它们制作的稳定代码曾经不可避免地不可避免的变化,对于其他开发人员来说更可读.

适配器

适配器适应主体(适应器)到不同的接口.这样,我们可以将对象添加到名义上不同类型的集合中.

适配器仅将相关方法暴露于客户端,可以限制所有其他方法,揭示特定上下文的用法意图,例如调整外部库,使其显得不那么一般,更专注于我们的应用程序需求.适配器提高了我们代码的可读性和自我描述.

适配器将一个团队从其他团队中避免一次性挥发性代码;与海上团队打交道时的救生工具; - )

较少提及的目的是防止主题类的过量注释.有了这么多基于注释的框架,这变得比以往更重要.

适配器有助于仅对单个继承的Java限制.它可以在一个信封下结合几个适应症,给人以多种继承的印象.

代码明智,适配器是"薄".除了简单地调用Adaptee方法以及偶尔进行此类调用所需的数据转换外,它不应为Adaptee类添加太多代码.

JDK或基本库中没有很多好的适配器示例.应用程序开发人员创建适配器,以使库适应应用程序特定接口.

装饰

Decorator不仅委派,不仅将一种方法映射到另一种方法,还可以做更多的事情,它们修改了某些主题方法的行为,它可以完全决定不调用主题方法,并委派给另一个对象,一个辅助对象.

装饰器通常将(透明地)功能添加到包装对象中,例如记录,加密,格式化或对主题的压缩.这种新功能可能会带来许多新代码.因此,装饰师通常比适配器大得多.

装饰器必须是受试者界面的子类.它们可以透明地使用,而不是其主题.请参阅BufferedOutputStream,它仍然是OutputStream,可以这样使用.这与适配器是主要的技术区别.

整体装饰家族的教科书示例很容易在JDK- Java IO中.所有类,例如 bufferedoutputputstream " http://docs.oracle.com/javase/8/docs/api/java/io/filteroutputstream.html" rel =" noreferrer"> filteroutputstream 和 Objectoututputstream outputStream .它们可以是洋葱分层的,在那里再次装饰一个装饰器,增加了更多功能.

代理

代理不是典型的包装纸.包装的对象,即代理主题,在代理创建时可能尚不存在.代理通常会在内部创建它.它可能是按需创建的重对象,也可能是不同的JVM或不同网络节点中的远程对象,甚至是非Java对象,是本机代码中的一个组件.它根本不需要包裹或委派给另一个对象.

最典型的示例是远程代理,重对象初始化器和访问代理.

  • 远程代理 - 主题在远程服务器上,不同的JVM甚至非非 Java系统.代理将方法调用转换为RMI/REST/SOAP调用或 无论需要什么,都可以屏蔽客户接触到基础 技术.

  • 懒负载代理 - 完全初始化对象的第一个用法或 第一个密集使用.

  • 访问代理 - 控制对主题的访问.

立面

立场与最少知识的设计原理密切相关(Demeter定律). 立面与适配器非常相似.它们都包裹,都将一个对象映射到另一个对象,但意图有所不同.地板使主题,复杂对象图的复杂结构变平,简化了对复杂结构的访问.

外墙包裹一个复杂的结构,为其提供平坦的界面.这样可以防止客户对象暴露于主题结构中的内部关系,从而促进松散的耦合.

更复杂的适配器模式变体,其中实现不仅会有所不同,而且抽象也有所不同.它为委派增加了一个间接.额外的代表团是桥梁.它即使无法调整接口也将适配器解散.它比其他任何其他包装模式都增加了复杂性,因此请注意.

构造函数的差异

图案差异在查看其构造函数时也很明显.

  • 代理没有包装现有对象.构造函数中没有主题.

  • 装饰器和适配器确实已经存在对象,并且通常是
    在构造函数中提供.

  • 幕墙构造函数构造函数获取整个对象图的根元素,否则看起来 与适配器相同.

Real life example – jaxb编组适配器.此适配器的目的是将简单的平面类映射到外部需要更复杂的结构,并防止"污染"主题类别具有过多的注释.

本文地址:https://www.itbaoku.cn/post/627468.html

问题描述

I was looking at the Proxy Pattern, and to me it seems an awful lot like the Decorator, Adapter, and Bridge patterns. Am I misunderstanding something? What's the difference? Why would I use the Proxy pattern versus the others? How have you used them in the past in real world projects?

推荐答案

Proxy, Decorator, Adapter, and Bridge are all variations on "wrapping" a class. But their uses are different.

  • Proxy could be used when you want to lazy-instantiate an object, or hide the fact that you're calling a remote service, or control access to the object.

  • Decorator is also called "Smart Proxy." This is used when you want to add functionality to an object, but not by extending that object's type. This allows you to do so at runtime.

  • Adapter is used when you have an abstract interface, and you want to map that interface to another object which has similar functional role, but a different interface.

  • Bridge is very similar to Adapter, but we call it Bridge when you define both the abstract interface and the underlying implementation. I.e. you're not adapting to some legacy or third-party code, you're the designer of all the code but you need to be able to swap out different implementations.

  • Facade is a higher-level (read: simpler) interface to a subsystem of one or more classes. Suppose you have a complex concept that requires multiple objects to represent. Making changes to that set of objects is confusing, because you don't always know which object has the method you need to call. That's the time to write a Facade that provides high-level methods for all the complex operations you can do to the collection of objects. Example: a Domain Model for a school section, with methods like countStudents(), reportAttendance(), assignSubstituteTeacher(), and so on.

其他推荐答案

As Bill's answer says, their use cases are different.

So are their structures.

  • Proxy and Decorator both have the same interface as their wrapped types, but the proxy creates an instance under the hood, whereas the decorator takes an instance in the constructor.

  • Adapter and Facade both have a different interface than what they wrap. But the adapter derives from an existing interface, whereas the facade creates a new interface.

  • Bridge and Adapter both point at an existing type. But the bridge will point at an abstract type, and the adapter might point to a concrete type. The bridge will allow you to pair the implementation at runtime, whereas the adapter usually won't.

其他推荐答案

My take on the subject.

All four patterns have a lot in common, all four are sometimes informally called wrappers, or wrapper patterns. All use composition, wrapping subject and delegating the execution to the subject at some point, do mapping one method call to another one. They spare client the necessity of having to construct a different object and copy over all relevant data. If used wisely, they save memory and processor.

By promoting loose coupling they make once stable code less exposed to inevitable changes and better readable for fellow developers.

Adapter

Adapter adapts subject (adaptee) to a different interface. This way we can add object be placed to a collection of nominally different types.

Adapter expose only relevant methods to client, can restrict all others, revealing usage intents for particular contexts, like adapting external library, make it appear less general and more focused on our application needs. Adapters increase readability and self description of our code.

Adapters shields one team from volatile code from other teams; a life savior tool when dealing with offshore teams ;-)

Less mentioned purpose it to prevent the subject class from excess of annotations. With so many frameworks based on annotations this becomes more important usage then ever.

Adapter helps to get around Java limitation of only single inheritance. It can combine several adaptees under one envelope giving impression of multiple inheritance.

Code wise, Adapter is “thin”. It should not add much code to the adaptee class, besides simply calling the adaptee method and occasional data conversions necessary to make such calls.

There are not many good adapter examples in JDK or basic libraries. Application developers create Adapters, to adapt libraries to application specific interfaces.

Decorator

Decorator not only delegate, not only maps one method to another, they do more, they modify behaviour of some subject methods, it can decide not call subject method at all, delegate to a different object, a helper object.

Decorators typically add (transparently) functionality to wrapped object like logging, encryption, formatting, or compression to subject. This New functionality may bring a lot of new code. Hence, decorators are usually much “fatter” then Adapters.

Decorator must be a sub-class of subject's interface. They can be used transparently instead of its subjects. See BufferedOutputStream, it is still OutputStream and can be used as such. That is a major technical difference from Adapters.

Text book examples of whole decorators family is readily in JDK - the Java IO. All classes like BufferedOutputStream, FilterOutputStream and ObjectOutputStream are decorators of OutputStream. They can be onion layered, where one one decorator is decorated again, adding more functionality.

Proxy

Proxy is not a typical wrapper. The wrapped object, the proxy subject, may not yet exist at the time of proxy creation. Proxy often creates it internally. It may be a heavy object created on demand, or it is remote object in different JVM or different network node and even a non-Java object, a component in native code. It does not have to necessary wrap or delegate to another object at all.

Most typical examples are remote proxies, heavy object initializers and access proxies.

  • Remote Proxy – subject is on remote server, different JVM or even non Java system. Proxy translates method calls to RMI/REST/SOAP calls or whatever is needed, shielding client from exposure to underlying technology.

  • Lazy Load Proxy – fully initialize object only the first usage or first intensive usage.

  • Access Proxy – control access to subject.

Facade

Facade is closely associated with design Principle of Least Knowledge (Law of Demeter). Facade is very similar to Adapter. They both wrap, they both map one object to another, but they differ in the intent. Facade flattens complex structure of a subject, complex object graph, simplifying access to a complex structure.

Facade wraps a complex structure, providing a flat interface to it. This prevents client object from being exposed to inner relations in subject structure hence promoting loose coupling.

Bridge

More complex variant of Adapter pattern where not only implementation varies but also abstraction. It adds one more indirection to the delegation. The extra delegation is the bridge. It decouples Adapter even from adapting interface. It increases complexity more than any other of the other wrapping patterns, so apply with care.

Differences in constructors

Pattern differences are also obvious when looking at their constructors.

  • Proxy is not wrapping an existing object. There is no subject in constructor.

  • Decorator and Adapter does wrap already existing object, and such is typically
    provided in the constructor.

  • Facade constructor takes root element of a whole object graph, otherwise it looks same as Adapter.

Real life example – JAXB Marshalling Adapter. Purpose of this adapter is mapping of a simple flat class to more complex structure required externally and to prevent "polluting" subject class with excessive annotations.