Design Patterns

Structural Patterns

Patterns for composing classes and objects into larger structures while keeping those structures flexible — wrapping, adapting, and simplifying without changing the components underneath.
  • Adapter: converts one interface into another that a client expects — makes incompatible interfaces work together without modifying either side
  • Decorator: attaches new behavior to an object dynamically by wrapping it in another object with the same interface — an alternative to subclassing for extending behavior
  • Facade: provides a single simplified interface in front of a complex subsystem — hides complexity, doesn't add capability
  • Composite: treats individual objects and compositions of objects uniformly through a shared interface — the natural fit for tree structures
  • Proxy: stands in for another object, controlling access to it (lazy loading, access control, remote calls, caching) behind the same interface
Structural patterns — same shape, different intent
PatternWraps to…Changes the interface?
Adaptermake an incompatible interface fityes — translates one interface to another
Decoratoradd behavior transparentlyno — same interface, extra behavior
Proxycontrol access transparentlyno — same interface, extra control
Facadesimplify a subsystemyes — offers a smaller, simpler interface
Decorator — java.io is the canonical real-world example
interface DataSource { void write(String s); String read(); }

class FileDataSource implements DataSource { /* base behavior */ }

abstract class DataSourceDecorator implements DataSource {
    protected final DataSource wrapped;
    DataSourceDecorator(DataSource wrapped) { this.wrapped = wrapped; }
}

class CompressionDecorator extends DataSourceDecorator {
    CompressionDecorator(DataSource wrapped) { super(wrapped); }
    public void write(String s) { wrapped.write(compress(s)); }
    public String read() { return decompress(wrapped.read()); }
}

// Stack decorators freely — this is exactly what new BufferedReader(new InputStreamReader(in)) does
DataSource source = new CompressionDecorator(new EncryptionDecorator(new FileDataSource()));
`java.io`'s stream classes (BufferedInputStream wrapping a FileInputStream, etc.) are Decorator applied throughout the standard library
Sources
  • Head First Design Patterns (2nd ed.)Ch. 3, 7 — Decorator; Adapter and Facade