HuntExams Academy logo
JavaAdvanced#design-patterns

What is the difference between the Adapter and Decorator patterns?

Answer

Adapter converts one interface into another that a client expects, bridging incompatible interfaces. Decorator wraps an object to add new behavior dynamically without altering its interface or subclassing.

Example

// Adapter: makes LegacyPrinter usable as Printer
class PrinterAdapter implements Printer { LegacyPrinter lp; public void print(String s) { lp.oldPrint(s); } }
// Decorator: adds behavior
InputStream in = new BufferedInputStream(new FileInputStream("f.txt"));

Detailed explanation

Adapter and Decorator are structural design patterns that commonly use composition: one object holds another object and delegates work to it. Their main difference is intent. An Adapter makes an existing object usable through an interface that a client expects, even though the object's original interface is incompatible. A Decorator preserves the component's contract while adding responsibilities, such as buffering, logging, or validation. In interviews, identifying this intent matters more than recognising a wrapper class, because their code structures can look very similar.

An object Adapter implements the target interface and stores a reference to the adaptee, usually supplied through its constructor. In the printer example, PrinterAdapter implements Printer, while LegacyPrinter exposes oldPrint(String) rather than print(String). The adapter's print method translates the client's request into a call to oldPrint. Real adapters may also convert arguments, map return values, or translate exceptions. The client depends only on Printer, so legacy or third-party code can be integrated without changing either the client's expected interface or the original implementation.

A Decorator implements or extends the same component abstraction as the object it wraps. It delegates operations while adding behaviour before, after, or around those calls. In Java I/O, both FileInputStream and BufferedInputStream are InputStream subclasses. Wrapping a FileInputStream in a BufferedInputStream adds buffering while allowing client code to continue using InputStream methods. Internally, the buffer can serve reads from memory and fetch larger chunks from the underlying stream when necessary. Decorators can be stacked, and their order may affect behaviour. They avoid creating a separate subclass for every combination of features, although concrete decorators may themselves use inheritance.

Choose Adapter when the problem is interface incompatibility; choose Decorator when the problem is adding responsibilities to an already compatible component. The distinction is about the contract presented to the client, not merely whether method names change. Interviewers also expect awareness that wrappers must handle delegation, exceptions, and resource ownership carefully. For stream decorators, closing the outer stream generally closes the wrapped stream, making try-with-resources a natural choice.

Key points to remember

  • Adapter bridges an incompatible existing interface to the interface a client expects.
  • Decorator adds responsibilities while preserving the component abstraction.
  • Both commonly use composition and delegation; intent distinguishes them.
  • Adapters may translate calls, data, results, and exceptions; decorators enhance operations.
  • Decorators support feature combinations through stacking, but wrapping order can matter.

Common mistakes candidates make

  • Calling every wrapper an Adapter or Decorator without explaining its purpose.
  • Claiming Decorator never uses inheritance: it avoids subclassing for every feature combination, not all inheritance.
  • Assuming decorator order and resource handling are irrelevant because the component abstraction stays the same.

Likely follow-up questions

Does an Adapter always require inheritance?

No. An object adapter uses composition, implementing the target interface and holding the adaptee. Java's single class inheritance makes composition especially useful when adapting existing classes.

How is Decorator different from Proxy?

Decorator primarily adds responsibilities to a component, while Proxy primarily controls access to another object, for example through lazy loading or remote invocation. Both can expose the same abstraction and delegate calls, so distinguish them by their intended role.

Can an Adapter and a Decorator be used together?

Yes. First adapt a LegacyPrinter to Printer, then wrap that Printer in a logging decorator that also implements Printer. The adapter solves compatibility, while the decorator adds logging independently.

Interview tip: Start with “Adapter changes compatibility; Decorator adds responsibility,” then explain the printer adapter and buffered stream examples.

Related Interview Questions

1
JavaAdvanced#design-patterns#oop

What is the difference between composition and inheritance, and why is 'favor composition over inheritance' recommended?

Open
2
JavaAdvanced#design-patterns

What is the Template Method pattern?

Open
3
JavaBeginner#jdbc

What is JDBC and what are its main components?

Open