What are the top must-know software design patterns?
The top must-know software design patterns are Singleton, Factory Method, Abstract Factory, Builder, Prototype, Adapter, Composite, Proxy, Facade, Flyweight, Observer, Strategy, Command, State, and Mediator. Every one of them falls into one of three types: creational, structural, or behavioral.
This guide explains what each of these design patterns does, when to use it, and shows a short code example for every pattern.
What Are Software Design Patterns?
A software design pattern is a reusable, named solution to a design problem that shows up again and again in object-oriented code. A pattern is not a library or a piece of code you copy. It is a template: it describes the problem, the solution, and the trade-offs, and you adapt it to your own codebase.
The idea was popularized by the "Gang of Four" (GoF) book, Design Patterns: Elements of Reusable Object-Oriented Software, which cataloged 23 classic patterns. You do not need all 23 to write good software or to pass an interview. The 15 patterns in this guide cover the vast majority of real-world use.
The 3 Types of Design Patterns
Design patterns are grouped into three categories: creational, structural, and behavioral. Each category solves a different kind of problem.
| Type | What it solves | Must-know patterns |
|---|---|---|
| Creational | How objects get created, hiding the messy construction details | Singleton, Factory Method, Abstract Factory, Builder, Prototype |
| Structural | How classes and objects are composed into larger structures | Adapter, Composite, Proxy, Facade, Flyweight |
| Behavioral | How objects communicate and share responsibilities | Observer, Strategy, Command, State, Mediator |
Why Design Patterns Matter
- They solve proven problems: Patterns are battle-tested solutions, so you avoid reinventing (and re-breaking) the wheel.
- They give teams a shared vocabulary: Saying "use a Facade here" communicates a full design in three words.
- They improve code quality: Patterns push you toward loosely coupled, reusable, and maintainable structures.
- They prepare you for interviews: Object-oriented design interviews and low-level design (LLD) rounds lean heavily on these 15 patterns.
Creational Design Patterns
Creational design patterns deal with object creation. They hide the construction logic so the rest of the system does not depend on how its objects are built. Here are the five creational patterns worth knowing cold.
1. Singleton Pattern
- What it does: Ensures that a class has only one instance and provides a global point of access to it.
- Example: A database connection pool. Creating multiple pools would flood the database with connections. The Singleton pattern guarantees one pool, accessible everywhere.
public class DatabaseConnection { private static DatabaseConnection instance; private DatabaseConnection() {} public static synchronized DatabaseConnection getInstance() { if (instance == null) { instance = new DatabaseConnection(); } return instance; } }
2. Factory Method Pattern
- What it does: Defines an interface for creating an object, but lets subclasses decide which concrete class to instantiate.
- Example: A logistics system where the transport type is decided at runtime. Each subclass picks its own transport without changing the delivery-planning code.
abstract class Logistics { public abstract Transport createTransport(); public void planDelivery() { Transport transport = createTransport(); transport.deliver(); } } class RoadLogistics extends Logistics { @Override public Transport createTransport() { return new Truck(); } }
3. Abstract Factory Pattern
- What it does: Provides an interface for creating families of related objects without specifying their concrete classes.
- Example: A UI toolkit where buttons and checkboxes must look consistent per platform. Each factory produces a matching family of components.
interface GUIFactory { Button createButton(); Checkbox createCheckbox(); } class WinFactory implements GUIFactory { public Button createButton() { return new WinButton(); } public Checkbox createCheckbox() { return new WinCheckbox(); } }
4. Builder Pattern
- What it does: Constructs complex objects step by step, so the same construction code can produce different representations.
- Example: A meal planner where a meal is assembled from burgers, drinks, and sides. The builder absorbs all the variations.
class MealBuilder { private Meal meal = new Meal(); public MealBuilder addBurger(String type) { /* ... */ } public MealBuilder addDrink(String type) { /* ... */ } public Meal build() { return meal; } }
5. Prototype Pattern
- What it does: Creates new objects by cloning an existing object (the prototype). Useful when building an object from scratch is more expensive than copying one.
- Example: A game that needs thousands of similar tree objects. Instead of constructing each tree, clone a prototype and tweak its properties.
class Tree implements Cloneable { private String type; private Color color; private Position position; public Tree clone() { // Create a deep copy of this tree object. } }
Creational patterns make a system independent of how its objects are created, composed, and represented. That independence is what keeps construction changes from rippling through the codebase.
Structural Design Patterns
Structural design patterns are concerned with how classes and objects are composed into larger structures. They simplify a design by identifying clean relationships between entities. These are the five structural patterns to know.
1. Adapter Pattern (Wrapper)
- What it does: Lets an existing class work through a different interface, without modifying its source code.
- Example: Your application produces customer data in JSON, but a third-party billing system expects XML. An adapter converts between the two so neither side changes.
// Existing interface (XML input) interface BillingSystem { void processBilling(String customerDataXml); } // Adapter class BillingAdapter implements BillingSystem { private JsonBillingSystem jsonBillingSystem = new JsonBillingSystem(); @Override public void processBilling(String customerDataJson) { String customerDataXml = convertJsonToXml(customerDataJson); jsonBillingSystem.processBilling(customerDataXml); } private String convertJsonToXml(String json) { // Conversion logic return "<xml>"; } }
2. Composite Pattern
- What it does: Composes objects into tree structures to represent part-whole hierarchies, so clients treat single objects and groups of objects the same way.
- Example: A graphics editor where shapes can be grouped into diagrams. Moving or drawing works identically on one circle or a whole group.
interface Graphic { void move(int x, int y); void draw(); } class CompositeGraphic implements Graphic { private List<Graphic> childGraphics = new ArrayList<>(); public void add(Graphic graphic) { childGraphics.add(graphic); } @Override public void move(int x, int y) { for (Graphic graphic : childGraphics) { graphic.move(x, y); } } @Override public void draw() { for (Graphic graphic : childGraphics) { graphic.draw(); } } }
3. Proxy Pattern
- What it does: Provides a placeholder for another object to control access to it: for security, caching, or lazy loading of an expensive object.
- Example: An image loader proxy that defers loading a high-resolution image from disk until the image actually needs to be displayed.
interface Image { void display(); } class HighResolutionImage implements Image { public HighResolutionImage(String imagePath) { // Load image from disk (heavy operation) } @Override public void display() { // Display the image } } class ImageLoaderProxy implements Image { private String imagePath; private HighResolutionImage highResImage; public ImageLoaderProxy(String imagePath) { this.imagePath = imagePath; } @Override public void display() { if (highResImage == null) { highResImage = new HighResolutionImage(imagePath); } highResImage.display(); } }
4. Facade Pattern
- What it does: Provides one simplified interface to a complex subsystem of classes, a library, or a framework.
- Example: A home theater facade that hides the projector, sound system, and lights behind a single watchMovie() call.
class HomeTheaterFacade { private Projector projector; private SoundSystem soundSystem; private Lights lights; public HomeTheaterFacade(Projector projector, SoundSystem soundSystem, Lights lights) { this.projector = projector; this.soundSystem = soundSystem; this.lights = lights; } public void watchMovie() { lights.dim(); soundSystem.turnOn(); projector.turnOn(); // Setup more components... } }
5. Flyweight Pattern
- What it does: Cuts the cost of creating huge numbers of similar objects by sharing their common state instead of duplicating it in every object.
- Example: A text editor rendering millions of characters. Each character object shares the intrinsic state (the glyph), while position and font are passed in from outside.
class Character { private char glyph; // Intrinsic state public Character(char glyph) { this.glyph = glyph; } public void display(int fontSize, int positionX, int positionY) { // Display character with extrinsic state } }
Structural patterns keep an architecture easy to understand and extend. In interviews, Adapter, Facade, and Proxy come up constantly because real systems integrate with other systems all the time.
Behavioral Design Patterns
Behavioral design patterns are concerned with how objects communicate and how responsibilities are divided between them. They make interactions flexible and loosely coupled. These five are the ones to master.
1. Observer Pattern
- What it does: Defines a one-to-many dependency so that when one object changes state, all its dependents are notified automatically.
- Example: A weather station broadcasting updates to a phone app, a billboard, and a website. Each display updates itself whenever new data is published.
interface Observer { void update(float temperature, float humidity, float pressure); } interface Subject { void registerObserver(Observer o); void removeObserver(Observer o); void notifyObservers(); } class WeatherStation implements Subject { private List<Observer> observers; private float temperature; private float humidity; private float pressure; // methods to manage observers and notify them }
2. Strategy Pattern
- What it does: Defines a family of interchangeable algorithms and lets the client pick one at runtime, independent of the code that uses it.
- Example: A navigation app that switches between shortest route, least traffic, and scenic route without changing the route-building code.
interface RouteStrategy { List<Point> calculateRoute(Point A, Point B); } class NavigationApp { private RouteStrategy routeStrategy; public void setRouteStrategy(RouteStrategy routeStrategy) { this.routeStrategy = routeStrategy; } public void buildRoute(Point A, Point B) { List<Point> route = routeStrategy.calculateRoute(A, B); // Display the route } }
3. Command Pattern
- What it does: Wraps a request in an object, so requests can be queued, scheduled, logged, or undone.
- Example: A smart home where "lights on" or "lock doors" are command objects that can be executed now, scheduled for later, or reversed.
interface Command { void execute(); } class LightOnCommand implements Command { private Light light; public LightOnCommand(Light light) { this.light = light; } @Override public void execute() { light.on(); } } class RemoteControl { private Command command; public void setCommand(Command command) { this.command = command; } public void pressButton() { command.execute(); } }
4. State Pattern
- What it does: Lets an object change its behavior when its internal state changes, without giant if/else chains in the client code.
- Example: An order that moves through New, Approved, Packed, Shipped, and Delivered. Each state object owns the behavior for that stage.
interface State { void next(Order order); void prev(Order order); void printStatus(); } class Order { private State state; public Order() { state = new NewState(); } public void nextState() { state.next(this); } public void previousState() { state.prev(this); } public void setState(State state) { this.state = state; } public void printStatus() { state.printStatus(); } }
5. Mediator Pattern
- What it does: Centralizes communication between objects in one mediator, so objects never reference each other directly.
- Example: A chat room. Users send messages to the room, and the room forwards them. No user talks to another user directly.
interface ChatRoomMediator { void showMessage(User user, String message); } class ChatRoom implements ChatRoomMediator { @Override public void showMessage(User user, String message) { System.out.println(user.getName() + ": " + message); } }
Behavioral patterns define not just what objects do but how they talk to each other. That is usually where complexity hides, which is why Observer and Strategy are the two most frequently asked patterns in design interviews.
Design Patterns Cheat Sheet
Use this table as a quick reference when you are deciding which pattern fits a problem.
| Pattern | Type | Use it when you need to |
|---|---|---|
| Singleton | Creational | Guarantee exactly one instance (config, connection pool) |
| Factory Method | Creational | Let subclasses choose which class to instantiate |
| Abstract Factory | Creational | Create whole families of related objects |
| Builder | Creational | Assemble complex objects step by step |
| Prototype | Creational | Clone expensive objects instead of rebuilding them |
| Adapter | Structural | Make incompatible interfaces work together |
| Composite | Structural | Treat single objects and groups uniformly |
| Proxy | Structural | Control access, cache, or lazy-load an object |
| Facade | Structural | Hide a complex subsystem behind one simple interface |
| Flyweight | Structural | Share state across huge numbers of similar objects |
| Observer | Behavioral | Notify many objects when one object changes |
| Strategy | Behavioral | Swap algorithms at runtime |
| Command | Behavioral | Queue, schedule, or undo requests |
| State | Behavioral | Change behavior as internal state changes |
| Mediator | Behavioral | Decouple objects that talk to each other |
How to Learn Design Patterns
A practical order that works well:
- Start with the big five: Singleton, Factory Method, Strategy, Observer, and Adapter. These appear most often in real codebases and in interviews.
- Learn the categories, not just the patterns: If you can explain why a problem is creational vs. structural vs. behavioral, choosing the right pattern becomes mechanical.
- Implement each pattern once: Reading about Builder is not the same as writing one. A 30-line toy implementation cements it.
- Spot patterns in code you already use: Java's Runtime is a Singleton, java.util.Iterator is the Iterator pattern, and every UI listener is an Observer.
From Design Patterns to System Design Patterns
The patterns above solve problems inside a single codebase. Modern interviews also test the same idea one level up: patterns for entire distributed systems, such as caching, sharding, load balancing, and event-driven architecture. Our newest course, System Design Patterns: From Fundamentals to Real Systems, teaches these architecture-level patterns and shows how real systems combine them. For a written overview, start with our complete guide to system design patterns.
If you are preparing for interviews, pair it with Grokking the System Design Interview to practice applying these patterns to real interview questions.
Frequently Asked Questions
What are the 3 types of design patterns?
The three types are creational (object creation), structural (object composition), and behavioral (object communication). Every classic design pattern belongs to one of these categories.
What are the 23 Gang of Four design patterns?
The GoF book catalogs 23 patterns: 5 creational, 7 structural, and 11 behavioral. The 15 covered in this guide are the subset you will actually use and be asked about; the remaining ones (such as Bridge, Visitor, Memento, Interpreter, and Chain of Responsibility) are worth reading once but rarely come up.
Which design patterns should I learn first?
Singleton, Factory Method, Strategy, Observer, and Adapter. They are the most common in production code, and most interview questions build on them.
Are design patterns still relevant?
Yes. Frameworks have absorbed some patterns (dependency injection containers reduce hand-written Singletons, for example), but the underlying ideas power those frameworks, and interviewers still expect you to know them. The vocabulary also carries directly into system design, where the same thinking applies at the architecture level.
Conclusion
Software design patterns are proven solutions to recurring design problems. Master the 15 patterns in this guide, know which of the three categories each belongs to, and be able to sketch one example per pattern. That is enough for the overwhelming majority of code reviews, low-level design rounds, and object-oriented interviews. When you are ready to apply the same pattern thinking to large-scale architecture, continue with System Design Patterns: From Fundamentals to Real Systems.

GET YOUR FREE
Coding Questions Catalog

$197

$72

$78