Structural patterns describe how to assemble classes and objects into larger structures while keeping those structures flexible and efficient. The Adapter pattern converts the interface of a class into another interface that clients expect, allowing otherwise incompatible classes to work together. A common analogy is a power plug adapter that lets a US plug fit a European socket. There are two main forms: a class adapter, which relies on multiple inheritance to adapt one interface to another, and an object adapter, which uses composition to wrap an existing class and is generally preferred. The Bridge pattern decouples an abstraction from its implementation so the two can vary independently. A Shape abstraction paired with a Color implementation, for instance, can produce combinations such as RedCircle or BlueSquare without needing a class for every possible combination, preventing a cartesian product explosion of subclasses when multiple dimensions of variation exist.
The Composite pattern composes objects into tree structures to represent part-whole hierarchies, allowing clients to treat individual objects and compositions uniformly. A file system, where both files and directories implement a common component interface, is a classic example; the interface lets client code call the same operation on leaves and on groups of leaves alike. The Decorator pattern attaches additional responsibilities to an object dynamically, offering a flexible alternative to subclassing. A decorator wraps the original object, implements the same interface, and adds behavior before or after delegating to the wrapped object. Java's I/O streams are a familiar example, where buffering, character conversion, and other features are layered on top of a basic file input stream. Decorators are useful when responsibilities need to be added dynamically without affecting other objects, when subclassing would explode the number of classes, or when behaviors should be combined flexibly at runtime, as in middleware stacking or adding logging, caching, or authentication to services.
The Facade pattern provides a simplified interface to a complex subsystem without adding new functionality, making existing functionality easier to use. A HomeTheaterFacade, for example, might expose a watchMovie method that internally turns on the projector, dims the lights, and starts the player, reducing coupling between clients and the underlying components. The Flyweight pattern reduces memory usage by sharing common state among many objects while keeping unique state external. Intrinsic state, such as the font used to render a character, can be shared across all character objects, while extrinsic state, such as position, is supplied by the client at use time. This pattern is appropriate when an application must support a very large number of similar objects and most of their state can be made extrinsic. The Proxy pattern provides a surrogate or placeholder for another object to control access to it, with common variants including virtual proxies that delay the creation of expensive objects, protection proxies that check permissions, remote proxies that represent objects in a different address space, and caching proxies that store results of expensive operations.
Several of these patterns share structural similarities but differ in intent, and understanding the distinctions is essential for choosing among them. Adapter and Facade both wrap other classes, but an Adapter makes an existing interface compatible with another expected interface and typically wraps a single class, while a Facade simplifies a complex subsystem made up of many classes — Adapter is about interoperability, Facade about convenience. Bridge and Adapter also share structure, but an Adapter is a retrofit applied after a system is designed to bridge incompatible interfaces, whereas a Bridge is a planned decoupling introduced upfront to let abstraction and implementation vary independently. Composite and Decorator both rely on recursive composition, but Composite focuses on representing part-whole hierarchies while Decorator focuses on adding behavior to individual objects. Finally, Decorator and Proxy both wrap an object and implement the same interface, but Decorator adds new responsibilities chosen by the client, whereas Proxy controls access without necessarily adding behavior and is typically transparent to the client.