skip to content

Decorator and Proxy have almost identical structure — both wrap an object behind the same interface. How do you tell them apart, and how do both differ from Adapter?

level: middleimportance: must knowfreq 58%

answer

  1. same shape, different intent
  2. Decorator adds; Proxy governs access
  3. Adapter changes the interface
  4. proxy usually owns/creates the subject
  5. decorators stack; proxies usually do not

basics

~20 s

Decorator adds extra behavior to an object; Proxy controls access to it (lazy creation, remote calls, permission checks, lifecycle). Both keep the interface. Adapter is different again: it changes one interface into another so incompatible code can work together.

solid answer

~50 s

All three are wrappers; the difference is intent, not shape. **Decorator** adds responsibilities. The wrapped object is handed to it from outside, it always represents an existing object, and decorators are designed to be stacked in varying combinations chosen at runtime. **Proxy** controls access to a subject. Typical variants: virtual (create the expensive object only on first use), remote (the real object lives elsewhere), protection (authorization checks), smart reference (reference counting, locking, lazy loading of ORM associations). A proxy usually *owns or creates* the subject rather than receiving it, and there is normally one proxy, not a stack. The client often does not even know a proxy exists. **Adapter** converts an interface: the client expects `Target`, the existing class offers `Adaptee`, and the adapter translates. It deliberately does *not* preserve the interface — that is its whole point. Rule of thumb: same interface + more behavior = Decorator; same interface + gate/indirection = Proxy; different interface = Adapter.

go deeper

for a junior

State the one-liners: Decorator adds behavior, Proxy controls access, Adapter changes the interface — with one example each.

for a middle

Explain that structure is identical for Decorator and Proxy and that intent decides, then name proxy variants (virtual, remote, protection, smart reference) and give the stacking difference.

for a senior

Handle the grey areas honestly (caching, framework-generated proxies), relate to Composite/Chain of Responsibility/Strategy, and note that both proxies and decorators miss self-calls.

for a principal

Discuss when to stop hand-writing wrappers and adopt generated proxies or an interceptor pipeline, and the governance cost of implicit framework proxies versus explicit, readable decoration.

## Why the confusion exists Decorator, Proxy, Adapter (object form), and to a lesser degree Composite and Chain of Responsibility all use the same mechanism: an object holding a reference to another object and forwarding calls. Structural diagrams for Decorator and Proxy are essentially identical. The Gang of Four classify patterns by **intent**, not by class diagram — so the discriminating question is always *why does the wrapper exist?* ## Decorator: add responsibilities - **Intent:** attach additional behavior to an individual object dynamically. - **Interface:** identical to the wrapped type (transparency is required). - **Wrappee:** supplied by the caller/wiring code; the decorator does not decide what it wraps. - **Cardinality:** built to stack — `metrics(cache(retry(real)))` — and combinations vary per environment. - **Examples:** buffering/compressing/encrypting stream wrappers; adding logging, caching, retries, or metrics to a service; adding scrollbars or borders to a UI widget; wrapping a collection to make it read-only or synchronized. ## Proxy: control access - **Intent:** provide a surrogate or placeholder that controls access to another object. - **Interface:** also identical — but the extra code is about *whether, when, and where* the real call happens, not about enriching the result. - **Subject:** typically created, located, or lifecycle-managed by the proxy itself; often the client cannot supply it. - **Cardinality:** normally one proxy, not a configurable stack. - **Canonical variants:** - *Virtual proxy* — defers construction of an expensive object until first use (lazy-loaded ORM associations, image placeholders). - *Remote proxy* — local stand-in for an object in another process or machine; hides marshalling and network calls (RPC/RMI client stubs). - *Protection proxy* — enforces permissions before forwarding. - *Smart reference* — reference counting, locking, copy-on-write, usage tracking. ## Adapter: convert the interface - **Intent:** make an existing class usable through an interface the client already expects. - **Interface:** deliberately *different* from the adaptee's. The adapter implements `Target` while holding (object adapter) or inheriting (class adapter) the `Adaptee`. - **Cardinality:** one adapter per mismatched pair; adapters are not stacked for effect. - **Examples:** wrapping a third-party payment SDK behind your own `PaymentGateway` interface; making a legacy `enumerate()` API satisfy a modern iterator contract. ## Quick discriminator | Question | Decorator | Proxy | Adapter | |---|---|---|---| | Does the wrapper expose the same interface? | yes | yes | no | | Is the point to *add* capability? | yes | no | no | | Is the point to *govern/relocate/defer* access? | no | yes | no | | Is the point to *translate* a contract? | no | no | yes | | Designed to stack in varying combos? | yes | rarely | no | | Who supplies the wrapped object? | the client/wiring | usually the wrapper itself | the client | ## Nearby relatives - **Composite** — same recursive shape but holds *many* children and models a part–whole tree; Decorator holds exactly one and adds behavior. A decorator can be described as a degenerate composite with a single child and added responsibility. - **Chain of Responsibility** — a chain of handlers where a handler may *stop* the chain and where the intent is to find a handler; decorators normally all participate and preserve the operation. - **Facade** — one simplified entry point over a whole subsystem, not a same-interface wrapper over one object. - **Strategy** — swaps an algorithm *inside* an object rather than layering behavior *around* it; it changes the guts, not the skin. - **Middleware/interceptor pipelines** — the same idea generalized: a linear chain of same-signature handlers around a core, typically configured centrally. ## Grey areas (and how to answer them well) A caching wrapper is arguably both: it adds a capability *and* prevents access to the real object. A logging wrapper that also enforces a rate limit blurs the line too. The honest interview answer is: the structure is one mechanism, the labels record intent, and in a code review what matters is that each wrapper has a single clear purpose and that the interface remains substitutable. Say which intent dominates and why, rather than insisting on a rigid taxonomy. One more practical distinction: many frameworks generate proxies automatically (dynamic proxies, bytecode subclasses) to implement transactions, security, and caching. Because these are generated, self-calls inside the target object bypass them — the same limitation decorators have, since both only intercept calls that cross the object boundary.

  • Is a lazy-loading wrapper a Decorator or a Proxy?
    A Proxy — specifically a virtual proxy. Its purpose is to defer creation and control when the real object is touched, not to enrich the operation. The give-away is that it creates the subject itself rather than being handed one.
  • Both Decorator and Composite hold references of the component type. What single check separates them?
    Cardinality plus intent: Composite holds a collection of children and aggregates them into a part–whole tree; Decorator holds exactly one wrappee and adds responsibility to it.
  • Can Decorator and Adapter appear in the same stack?
    Yes and it is common: adapt a third-party client to your interface, then decorate the adapted object with retry and metrics. The adapter sits innermost, closest to the foreign library.

A Decorator is a phone case: same phone, same buttons, extra protection, and you can add a grip on top of it. A Proxy is a receptionist: the same conversation, but she decides whether you get through, or reaches the person in another building for you. An Adapter is a travel plug: it does not add anything, it just makes an incompatible connector fit.

saying these in an interview costs you the question

  • "Decorator and Proxy are the same pattern with different names" — the structure matches but the intent, ownership, and stacking differ.
  • "Adapter adds functionality" — it translates a contract; adding behavior is not its job.
  • Using UML shape alone to classify a wrapper.
  • "A proxy must be on a different machine" — remote is only one of several proxy variants.
  • "Decorator changes the interface so callers can use new methods" — added public methods are invisible through the shared interface and defeat transparency.
  • Calling a Facade a Decorator because both wrap things — a Facade simplifies a whole subsystem behind a new, narrower interface.

context