Series: Design Patterns and Analysis | Part 3 of 4 > Developed during Master’s in Web Systems Projects
Continuing our series, after exploring how to build objects with flexibility using Creational Patterns, it’s time to understand how to structure them for better collaboration. Structural Design Patterns focus on how classes and objects are combined to form larger structures — without unnecessary complexity or tight coupling.
What Are Structural Patterns?
Structural patterns describe ways to compose objects and classes into larger systems, ensuring that changes in one part do not ripple destructively through the codebase.
They help with:
- Adapting interfaces that weren’t designed to work together
- Adding responsibilities dynamically
- Hiding internal complexity behind simpler interfaces
Types of Structural Patterns
Adapter
Converts the interface of a class into another expected by the client.
- Intent: Bridge between incompatible interfaces.
- Use When: You want to reuse an existing class but its interface doesn’t match.

class RoundHole {
boolean fits(RoundPeg peg) { ... }
}
class SquarePegAdapter extends RoundPeg {
private SquarePeg peg;
double getRadius() { ... } // converts square to round logic
}
Bridge
Decouples an abstraction from its implementation so they can evolve independently.
- Intent: Split logic into abstraction and implementation layers.
- Use When: You want to vary both abstractions and implementations.

interface Device {
void enable();
void disable();
}
class Remote {
protected Device device;
public void togglePower() {
if (device.isEnabled()) device.disable();
else device.enable();
}
}
Composite
Composes objects into tree structures and treats them uniformly.
- Intent: Treat individual objects and compositions the same way.
- Use When: You work with recursive structures like UI trees or file systems.

interface Graphic {
void draw();
}
class CompoundGraphic implements Graphic {
private List<Graphic> children;
void draw() {
for (Graphic child : children) child.draw();
}
}
Decorator
Adds responsibilities to objects dynamically.
- Intent: Wrap an object to extend its behavior.
- Use When: You want to avoid subclass explosion and keep things flexible.

interface DataSource {
void writeData(String data);
}
class CompressionDecorator implements DataSource {
private DataSource wrappee;
void writeData(String data) {
wrappee.writeData(compress(data));
}
}
Facade
Provides a simplified interface to a complex subsystem.
- Intent: Hide complexity and expose only what’s necessary.
- Use When: You need a clean API over complex internals.

class VideoConverter {
public File convert(String filename, String format) {
// interacts with many video-related classes internally
}
}
Flyweight
Shares common parts of state across many objects to save memory.
- Intent: Use sharing to support large numbers of fine-grained objects efficiently.
- Use When: You need to manage many objects with similar data (e.g., game tiles, fonts).

class TreeType {
String texture;
void draw(int x, int y) { ... }
}
Proxy
Acts as a placeholder for another object to control access, lazy load, or log.
- Intent: Control access to an object.
- Use When: You need extra logic around the real object without changing it.

class ImageProxy implements Image {
private RealImage realImage;
void display() {
if (realImage == null) realImage = new RealImage();
realImage.display();
}
}
Comparison Table
Pattern | Purpose | Best For |
---|---|---|
Adapter | Interface conversion | Legacy code, integration |
Bridge | Separate abstraction from implementation | UI frameworks, device control |
Composite | Recursive tree structure | Graphics, UIs, folders |
Decorator | Add behavior without subclassing | I/O streams, logging |
Facade | Simplify subsystem usage | API gateways, libraries |
Flyweight | Share objects for memory efficiency | Rendering engines, games |
Proxy | Access control | Virtual proxies, protection, caching |
Final Thoughts
Structural patterns help us compose systems with elegance, enabling adaptation, extension, and simplification of architecture without creating a domino effect of changes.
Next up, we’ll explore Behavioral Patterns — how to coordinate responsibilities and workflows flexibly.
Series Navigation
- Introduction: Analysis Patterns
- Previous: Part 2 - Creational Patterns
- Current: Part 3 - Structural Patterns
- Next: Part 4 - Behavioral Patterns
- Complete series: Analysis Patterns | Design Patterns Overview | Creational Patterns | Behavioral Patterns