ChatGPT解决这个技术问题 Extra ChatGPT

Difference between the Facade, Proxy, Adapter and Decorator design patterns?

What is the difference between the Facade, Proxy, Adapter, and Decorator design patterns?

From a generic point of view, such patterns seem to do the same thing, that is: wrap an API and provide access to it.

How to distinguish these patterns? How to discern when one pattern suits more than the others?

@gavenkoa the other question is only about proxy and decorator
Incredible as some closed question reveal themselves so useful.

v
v.karbovnichy

Adapter adapts a given class/object to a new interface. In the case of the former, multiple inheritance is typically employed. In the latter case, the object is wrapped by a conforming adapter object and passed around. The problem we are solving here is that of non-compatible interfaces.

Facade is more like a simple gateway to a complicated set of functionality. You make a black-box for your clients to worry less i.e. make interfaces simpler.

Proxy provides the same interface as the proxied-for class and typically does some housekeeping stuff on its own. (So instead of making multiple copies of a heavy object X you make copies of a lightweight proxy P which in turn manages X and translates your calls as required.) You are solving the problem of the client from having to manage a heavy and/or complex object.

Decorator is used to add more gunpowder to your objects (note the term objects -- you typically decorate objects dynamically at runtime). You do not hide/impair the existing interfaces of the object but simply extend it at runtime.

Now that you have decorator involved, you will probably want to know why the emphasis on the word object -- some languages (like Java) simply don't allow virtual inheritance (i.e. multiple inheritance as C++ does) to allow you to accomplish this at compile time.

Since we have dragged in multiple inheritances (and the dreaded diamond) you will look out for mixins -- which are ordered linear chaining of interfaces to get around the problems of multiple inheritance. However, mixins don't mix that well. And we end up with traits -- yes those stateless little blobs of behavior that you see pop-up all the time in template parameters in C++. Traits try to address the issues of composition and decomposition of behavior in an elegant manner while not going either for multiple inheritances or ordered chaining.


HTH! I have tried to put in as much as I can without being too vague. Excuse my inability to do better. I have read (PhD dissertation) papers on traits alone. My knowledge therefore is rather limited and I ain't good enough to fit in all patterns in this space ;)
You anticipated a future question about mixins and traits but I haven't seen them yet !
A good comparison link (via wikipedia) for the first three (the Decorator being quite different): NetObjectives
@Liviu Your link is dead. I assume you were originally pointing there, but the content now seems to be behind a login.
@Sheljohn Link updated :p : A good comparison link (via wikipedia) for the first three (the Decorator being quite different) NetObjectives (Retreiveing text, see "betweem": "One of the more frequent questions I get in class is "what's the difference betweem Adapter, Proxy, and Facade? They really seem the same to me".)
T
Tim Cooper

Facade

You could use a facade, for example, to make calls to an API easier. Take a look at this example of a remote facade. The idea here is that the full implementation of the code on the server is hidden away from the client. The client calls 1 API method which, in turn, can make 1 or more API calls on the server.

Adapter

A good example of this can be found here, on Wikipedia. A client object Source would like to call a method on another object Target, but that other object's interface differs to what the client is expecting.

Enter the adapter object.

It can take a call from the Source object and, behind the scenes, call the Target method which should be used.

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

As for Proxy, I don't have any experience of this design pattern.