Design Patterns in Java
When you cook often, you stop inventing every dish from scratch. You learn a few dependable methods, like "make a base, then add spices, then simmer", and reuse them for many recipes. Programmers do the same. Over the years they kept running into the same design problems, and the best answers got names. Those named answers are design patterns. A pattern isn't a piece of code to copy. It's an idea for how to arrange your classes so a common problem stops being a problem.
Where the 23 Patterns Come From
In 1994, four authors (Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, often called the "Gang of Four") wrote down 23 patterns they saw again and again in good software. Those 23 are still the shared vocabulary of developers today. When someone in a team says "let's put a facade in front of that", everyone knows what they mean.
The 23 fall into three families, based on the kind of problem they solve:
| Family | The question it answers | How many |
|---|---|---|
| Creational | How do we make objects, cleanly and safely? | 5 |
| Structural | How do we fit classes and objects together? | 7 |
| Behavioral | How do objects share work and talk to each other? | 11 |
Creational Patterns: Making Objects
| Pattern | In plain words | Everyday comparison | Seen in Java |
|---|---|---|---|
| Singleton | Only one object of this class may ever exist | A country has one president at a time | Runtime.getRuntime() |
| Factory Method | Let a subclass decide which object to create | Each branch of a courier company picks its own vehicle | Iterable.iterator() in each collection |
| Abstract Factory | Create a whole matching family of objects together | A furniture showroom that sells a matching sofa, table and chair in one style | DocumentBuilderFactory in XML APIs |
| Builder | Assemble a complicated object step by step | Ordering a pizza by choosing size, then toppings, then crust | StringBuilder, HttpRequest.newBuilder() |
| Prototype | Make new objects by copying a ready-made one | Photocopying a filled-in form and changing only the name | clone(), copy constructors |
Detailed lessons: "Creational Design Patterns", "Singleton Pattern in Java", "Factory Pattern in Java" and "Builder Pattern in Java".
Structural Patterns: Fitting Things Together
| Pattern | In plain words | Everyday comparison | Seen in Java |
|---|---|---|---|
| Adapter | Make one interface fit another that expects something different | A travel plug adapter for a foreign socket | Arrays.asList(array) |
| Bridge | Keep "what it does" and "how it's done" in separate class families | One TV remote design that works with many TV brands | JDBC: one API, many database drivers |
| Composite | Treat a group of things the same way as a single thing | A folder can hold files and other folders, and both have a size | GUI containers holding components |
| Decorator | Add extra features by wrapping an object | Adding milk, then sugar, to the same cup of coffee | new BufferedReader(new FileReader(...)) |
| Facade | Give one simple front door to a complicated system | One reception desk instead of visiting every hotel department | HttpClient hiding sockets and protocols |
| Flyweight | Share small common objects instead of making thousands of copies | Every seat in a cinema row points to the same "Premium" price card | Integer.valueOf cache, string pool |
| Proxy | A stand-in that controls access to the real object | A receptionist who decides whether you can meet the manager | Collections.unmodifiableList, Spring proxies |
Detailed lesson: "Structural Design Patterns".
Behavioral Patterns: Sharing the Work
| Pattern | In plain words | Everyday comparison | Seen in Java |
|---|---|---|---|
| Chain of Responsibility | Pass a request along a line of handlers until one takes it | A refund request goes to the team lead, then the manager, then the director | Servlet filters, logging handlers |
| Command | Turn an action into an object, so it can be stored, queued or undone | A waiter writes your order on a slip and hands it to the kitchen | Runnable tasks, undo in editors |
| Interpreter | Represent a small language as objects that can evaluate it | A calculator that understands "50 + 30 - 15" | java.util.regex.Pattern |
| Iterator | Walk through a collection without knowing how it's stored | Turning pages of a book without caring how it was bound | Iterator, the for-each loop |
| Mediator | Objects talk through one middle object instead of to each other | Planes talk to the control tower, not to every other plane | Chat rooms, java.util.Timer coordinating scheduled tasks |
| Memento | Save an object's state so it can be restored later | A save point in a video game | Undo history, serialization snapshots |
| Observer | Notify everyone who subscribed when something changes | YouTube notifies subscribers when a video is posted | Event listeners, PropertyChangeListener |
| State | An object changes its behavior when its internal state changes | A traffic light behaves differently when red, green or yellow | Order status flows, media players (play, pause, stop) |
| Strategy | Swap one algorithm for another behind the same interface | Choosing to pay by UPI, card or cash at the same counter | Comparator passed to sort |
| Template Method | A fixed recipe of steps where some steps are filled in later | Every hot drink: boil water, brew, pour, but brewing differs | AbstractList, InputStream.read |
| Visitor | Add new operations to a set of classes without changing them | A tax inspector visits different kinds of shops and applies different rules | FileVisitor in java.nio.file |
Detailed lessons: "Behavioral Design Patterns", "Strategy Pattern in Java" and "Observer Pattern in Java".
When Not to Use a Pattern
Patterns add classes and indirection. That's worth it only when the problem is real:
- Don't add a pattern "just in case". A factory around a class that will only ever have one version is clutter.
- Prefer the simplest thing that works. If a plain method solves it, write the method.
- Modern Java often needs less ceremony. Lambdas make Strategy and Command one-liners, enums make the safest Singleton, records cut down Builder-style boilerplate, and sealed types with
switchcan replace many Visitors.
Common Mistakes
Forcing a pattern into a small problem. Three extra classes around ten lines of logic make code harder, not better.
Mixing up similar patterns. Decorator adds features, Proxy controls access, Adapter changes the interface. All three wrap an object, but for different reasons.
Memorizing names without the problem. In interviews, explain the problem first, then the pattern.
Interview Corner
What are design patterns, and how are they classified?
Design patterns are proven, reusable solutions to common software design problems. The classic catalog by the Gang of Four has 23 patterns in three groups. Creational patterns deal with object creation: Singleton, Factory Method, Abstract Factory, Builder and Prototype. Structural patterns deal with combining classes and objects: Adapter, Bridge, Composite, Decorator, Facade, Flyweight and Proxy. Behavioral patterns deal with how objects interact and share responsibility: Chain of Responsibility, Command, Interpreter, Iterator, Mediator, Memento, Observer, State, Strategy, Template Method and Visitor.
Which design patterns does the JDK use?
Many. Singleton in Runtime.getRuntime(), Builder in StringBuilder, Factory methods in List.of and Integer.valueOf, Prototype in clone(), Adapter in Arrays.asList, Decorator in the java.io streams, Flyweight in the Integer cache, Proxy in Collections.unmodifiableList, Iterator in every collection, Strategy in Comparator, Observer in event listeners, Template Method in AbstractList and Visitor in FileVisitor.
Practice
- Easy: For each, name the pattern: a travel plug adapter, a save point in a game, a pizza order form, a control tower.
- Harder: Pick three patterns from different families and, for each, describe one place in an app you use daily (a food delivery or banking app) where it would fit.
Key Takeaways
Was this tutorial helpful?