32 articles in low level design › design patterns.
Learn the five SOLID principles by building a real order-processing system in Java, with before and after code for every principle.
A decision-oriented guide to all 23 GoF design patterns. Covers when to reach for each pattern, how they compare, and the flowcharts you need to pick the right one in interviews.
The factory method replaces direct constructor calls with a method that subclasses can override to return different types. Callers depend on an abstraction, not a concrete class.
How the abstract factory creates families of related objects without specifying their concrete classes, letting you swap product families by swapping the factory.
The builder separates complex object construction from representation, replacing telescoping constructors with a readable, fluent API that validates before building.
The singleton ensures a class has exactly one instance with a global access point. Thread-safe initialization, serialization safety, and testability are the three problems most implementations get wrong.
The prototype pattern creates new objects by cloning existing ones, avoiding expensive construction when you need many similar instances with minor variations.
The adapter pattern wraps an incompatible third-party interface so your code can use it through an interface it already expects. Structural bridging without changing either side.
Learn how the bridge pattern separates abstraction from implementation so both hierarchies grow independently, preventing class explosion when two axes of variation exist.
Learn how the composite pattern lets you treat individual objects and groups uniformly, building tree structures where clients never distinguish leaves from branches.
The decorator pattern wraps objects to add behavior at runtime without modifying the original class. Stack decorators like layers, each adding one responsibility while keeping the same interface.
The facade pattern provides a single, simplified interface to a complex subsystem with many classes. Clients call one method instead of orchestrating five.
The flyweight pattern minimizes memory by sharing common state across thousands of objects, splitting data into intrinsic (shared) and extrinsic (unique) parts.
The proxy pattern wraps an object to control access, add caching, or defer creation. Virtual, protection, and caching proxies all share one trick: same interface, different control.
Chain of responsibility passes a request along a handler pipeline until one processes it. Decouple senders from receivers with composable, reorderable handler chains.
The command pattern turns requests into objects so you can queue, log, and undo operations. Decouple sender from receiver by encapsulating actions.
The iterator pattern provides a uniform way to traverse any collection without exposing its internal structure. Decouple traversal logic from the data it walks over.
The mediator pattern routes all communication between objects through a central coordinator, replacing an O(N-squared) mesh of direct references with N connections to one hub.
The memento pattern captures an object's internal state as an opaque snapshot and restores it later, enabling undo and rollback without breaking encapsulation.
The observer pattern decouples event producers from consumers. A subject notifies all registered observers of state changes without knowing who they are or what they do.
The state pattern encapsulates state-specific behavior into separate objects, eliminating large switch statements and making each state's logic independently testable.
The strategy pattern extracts a family of algorithms behind an interface so the client can swap behaviors at runtime without touching the context class.
The template method defines an algorithm skeleton in a base class while letting subclasses override specific steps, enforcing the Hollywood Principle: don't call us, we'll call you.
The visitor pattern adds new operations to existing type hierarchies without modifying them, separating algorithms from the objects they operate on via double dispatch.
Eliminate null checks by providing a do-nothing implementation that conforms to the expected interface, making client code simpler and safer.
Decouple business logic from data access by encapsulating storage operations behind a collection-like interface, making persistence swappable and testable.
Separate an application into Model (data and rules), View (display), and Controller (input handling) so each layer can change independently.
Invert the dependency direction by injecting collaborators from outside rather than creating them internally, enabling testability and loose coupling.
Encapsulate business rules as composable, reusable objects that can be combined with AND, OR, and NOT operators for flexible filtering and validation.
Decouple game progression from hardware speed by running input, update, and render in a controlled loop with fixed or variable time steps.
Reuse a fixed set of worker threads to execute tasks from a shared queue, avoiding the overhead of creating and destroying threads per request.
Decouple producers from consumers using a shared bounded buffer so each side can work at its own pace without blocking or losing data.