skip to content

Structural Patterns

Patterns for composing classes and objects into larger structures: Adapter, Decorator, Proxy, Facade, Composite, Bridge and Flyweight. They mostly answer how two things that were not designed for each other can work together.

part ofSoftware design & architectureoverview, primer and where to startread it →
on this pageshow

questions

page 2 of 2

What signals tell you a facade has stopped helping and become a liability, and what would you do about each?

level: seniorimportance: should knowfreq 44%

basics

~20 s

Warning signs: it mirrors the subsystem method-for-method, it keeps growing into a god-object, it leaks internal types in its signatures, or nobody uses it because callers still import internals. Fix by resizing, splitting, or deleting it.

open as a page

How should the flyweight factory be implemented — the cache/interning strategy behind the Flyweight pattern — and what concurrency and lifetime issues does it introduce?

level: seniorimportance: should knowfreq 35%

basics

~20 s

The factory keeps a map from the shared-state key to the single instance, creating one only on a miss. It must be thread-safe, must not let two callers get two different instances for the same key, and must have a bounding or eviction policy so the map does not grow forever.

open as a page

How do you decide whether applying the Flyweight pattern will actually pay off, and when should you reject it?

level: seniorimportance: should knowfreq 30%

basics

~20 s

It pays off when you have very many objects but few distinct values, the duplicated part is big enough to matter, and the objects are long-lived. Reject it when values are mostly unique, the objects are few or short-lived, or the API damage outweighs the memory saved.

open as a page

Frameworks generate proxies at runtime to add transactions, security, or caching. How does that generation work, and what are its documented limitations?

level: seniorimportance: should knowfreq 40%

basics

~20 s

The framework returns a generated stand-in instead of your object: either a class implementing your interfaces, or a subclass of your class, that runs extra logic then delegates. Limitations: only calls that go through the returned reference are intercepted, so internal self-calls, final/private/static methods, and direct field access are not.

open as a page

Compare a protection proxy and a remote proxy: what does each control, and what specific hazards does each introduce?

level: seniorimportance: should knowfreq 45%

basics

~20 s

A protection proxy controls who may call — it checks the caller's rights and forwards or denies. A remote proxy controls where the object is — it hides that the real object lives in another process or machine. The first can be bypassed if callers reach the subject directly; the second hides latency and partial failure.

open as a page

The Bridge pattern is defined as 'decouple an abstraction from its implementation so that the two can vary independently.' What concrete problem does that solve, and how is Bridge different from Adapter and from Strategy?

level: seniorimportance: should knowfreq 48%

basics

~20 s

Bridge splits one concept into two hierarchies — what it does and how it is done — connected by composition, so you can extend either side without multiplying classes. Adapter reconciles two interfaces that already exist and clash; Bridge is designed up front. Strategy swaps one algorithm, not a whole implementation hierarchy.

open as a page

How is the Facade pattern used as an architectural boundary — for module public APIs, service SDKs, or a backend-for-frontend — and what changes about the trade-offs at that scale?

level: principalimportance: should knowfreq 36%

basics

~10 s

At architecture scale, a facade becomes a module's or service's single published entry point. Everything behind it can change freely; everything the facade exposes becomes a contract you must version, deprecate and support.

open as a page

At architecture scale, where do Facade, Proxy, Adapter and Decorator reappear as system-level building blocks, and what do you weigh before adding another layer of indirection?

level: principalimportance: should knowfreq 34%

basics

~20 s

The same intents scale up: an API gateway or service facade simplifies a subsystem, RPC client stubs and sidecars are proxies, anti-corruption layers are adapters, and middleware chains are decorators. Each layer buys decoupling but costs latency, one more hop to debug, and a contract someone must own.

open as a page

Must a facade be a single class, be stateless, or be a singleton — and how does introducing one affect testing of client code?

level: middleimportance: nice to knowfreq 26%

basics

~20 s

None of those are required. A facade can be several classes, hold state, and be created per use. For tests, clients now stub one facade instead of many collaborators, which makes their tests shorter — but the facade itself still needs integration tests.

open as a page

What are the main costs and failure modes of the Bridge pattern, and how do you tell when you have applied it badly?

level: seniorimportance: nice to knowfreq 25%

basics

~20 s

Bridge adds indirection and a second hierarchy to navigate, and forces you to design the interface between them early. It goes wrong when the interface mirrors the abstraction, leaks implementation details, or exists with only one implementation.

open as a page

Explain the Flyweight pattern's split between intrinsic and extrinsic state, and describe when the pattern actually pays for itself.

level: seniorimportance: nice to knowfreq 30%

basics

~20 s

Flyweight saves memory by sharing one object across many logical occurrences. The shared part (intrinsic state) is context-independent and immutable, such as a character's glyph shape; the varying part (extrinsic state) such as position or colour is passed in by the caller instead of stored per instance.

open as a page

Scaled up to whole-system boundaries, the Adapter pattern reappears as hexagonal architecture's "ports and adapters" and DDD's anti-corruption layer. What changes at that scale, and how do you decide how many adapters and how thick to make them?

level: principalimportance: nice to knowfreq 22%

basics

~20 s

At system scale the target interface becomes a "port" your domain owns, and each external system gets an adapter that translates its model into yours. This keeps vendor concepts out of the core, at the cost of extra layers and mapping code.

open as a page

Where does Bridge-style thinking show up above the class level — in module, plugin and system architecture — and what makes those seams succeed or fail?

level: principalimportance: nice to knowfreq 18%

basics

~20 s

The same idea scales up: a stable interface between a domain core and swappable technical mechanisms — ports and adapters, driver/plugin interfaces, storage or messaging abstractions. It succeeds when the seam is narrow, primitive and rarely changed.

open as a page

When is the Composite pattern the wrong choice, and what are the failure modes of an object tree at scale — persistence, depth, and heterogeneous leaves?

level: principalimportance: nice to knowfreq 22%

basics

~20 s

Composite fits only genuine part-whole hierarchies where nodes really share behaviour. It goes wrong when leaves differ too much to share a meaningful interface, when the tree is loaded lazily from a database (one query per node), or when depth comes from untrusted input and overflows the stack.

open as a page

When would you deliberately NOT use hand-written Decorator wrappers for cross-cutting behavior, and what would you use instead?

level: principalimportance: nice to knowfreq 21%

basics

~20 s

Skip decorators when the behavior applies uniformly to many types (use a middleware pipeline or framework interceptors), when there is only one fixed variation (put it in the class), or when the interface is too large or not designed for wrapping.

open as a page

What hazards arise from the shared, interned instances that the Flyweight pattern creates — around identity comparison, mutability, locking, serialization and multi-tenancy?

level: principalimportance: nice to knowfreq 18%

basics

~20 s

Because one object is shared everywhere, any mutation of it affects every user; comparing by reference works until an instance is created outside the factory or evicted; locking on a shared instance can make unrelated code contend or deadlock; and copies from serialization or other tenants silently break the "one instance" assumption.

open as a page

Beyond a single class, where does the Proxy pattern show up at the architecture level, and when is adding a proxy the wrong call?

level: principalimportance: nice to knowfreq 28%

basics

~20 s

The same idea scales up: API gateways, reverse proxies, service-mesh sidecars, caching layers, and database connection proxies all stand in front of something and control access to it. It's the wrong call when it adds a hop and an operating cost without policy — pure pass-through indirection.

open as a page

showing 31–47 of 47