Skip to main content

Introduction to Design Patterns

Reading Time: 8 Minutes
Difficulty: Beginner


Topic Summaryโ€‹

Design patterns are reusable solutions to commonly occurring problems in software design. They are not finished code โ€” they are templates or blueprints that you can adapt to solve a recurring problem in your project. Learning design patterns makes you a better programmer by giving you a shared vocabulary with other developers and proven solutions to common challenges.


What You'll Learnโ€‹

  • What design patterns are and why they exist
  • Who the "Gang of Four" are and why they matter
  • The three categories of patterns: Creational, Structural, and Behavioral
  • The difference between patterns and algorithms
  • Common design patterns used in Java

Prerequisitesโ€‹

  • No prerequisites, but solid understanding of Java OOP (classes, interfaces, inheritance) is recommended

Explanationโ€‹

What Are Design Patterns?โ€‹

Imagine you're building a house. Every house needs doors, windows, and a foundation โ€” problems that have been solved thousands of times. Instead of reinventing how a door frame works, you follow an established design.

In software, design patterns are the same idea. They are well-tested, named solutions to common design problems. They've been discovered, refined, and documented by experienced programmers over decades.

A design pattern:

  • Is not a library โ€” you can't import it and use it. You implement it yourself.
  • Is not a finished design โ€” it's a template you adapt to your situation.
  • Is a shared vocabulary โ€” when you say "this uses the Singleton pattern," every programmer immediately understands the structure.

The Gang of Four (GoF)โ€‹

In 1994, four computer scientists โ€” Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides โ€” wrote the landmark book:

"Design Patterns: Elements of Reusable Object-Oriented Software"

They catalogued 23 design patterns organized into three categories. These authors became known as the Gang of Four (GoF), and their patterns are still the foundation of software design today.


The Three Categoriesโ€‹

Creational Patterns โ€” How objects are createdโ€‹

These patterns deal with object creation mechanisms. Instead of creating objects directly with new, creational patterns provide smarter ways to create objects based on the situation.

PatternPurpose
SingletonEnsure only one instance exists
Factory MethodLet subclasses decide which object to create
Abstract FactoryCreate families of related objects
BuilderConstruct complex objects step by step
PrototypeClone existing objects

Example scenario: You want to ensure your database connection object is created only once and reused everywhere โ†’ Singleton.


Structural Patterns โ€” How objects are composedโ€‹

These patterns deal with how classes and objects are assembled into larger structures, making it easier to compose interfaces and implementations.

PatternPurpose
AdapterMake incompatible interfaces work together
BridgeSeparate abstraction from implementation
CompositeTreat individual objects and groups uniformly
DecoratorAdd behavior to objects without changing their class
FacadeProvide a simplified interface to a complex system
FlyweightShare fine-grained objects to save memory
ProxyProvide a surrogate or placeholder for another object

Example scenario: You have a legacy library with an incompatible interface โ†’ Adapter.


Behavioral Patterns โ€” How objects communicateโ€‹

These patterns deal with algorithms and the assignment of responsibilities between objects โ€” how they interact and divide work.

PatternPurpose
Chain of ResponsibilityPass requests along a chain of handlers
CommandEncapsulate a request as an object
InterpreterImplement a language's grammar
IteratorTraverse elements without exposing structure
MediatorReduce coupling by having objects communicate via a mediator
MementoSave and restore object state
ObserverNotify multiple objects about state changes
StateChange object behavior based on its state
StrategyDefine interchangeable algorithms
Template MethodDefine skeleton of algorithm in base class
VisitorAdd operations to objects without changing them

Example scenario: You have multiple algorithms for sorting and want to switch them at runtime โ†’ Strategy.


Design Patterns vs Algorithmsโ€‹

People often confuse patterns with algorithms:

AspectDesign PatternAlgorithm
What it isHigh-level template for structureStep-by-step procedure for computation
LevelArchitecture / OOP design levelCode / logic level
ExampleStrategy patternQuickSort implementation
Language-specific?No โ€” applies to any OOP languageOften yes
SolvesRecurring design problemsSpecific computational problems

An algorithm is like a recipe โ€” it tells you exactly what steps to follow. A pattern is like an architectural blueprint โ€” it tells you how to structure your solution, but you fill in the details.


Why Patterns Matterโ€‹

  1. Proven solutions: Patterns have been tested in real projects by thousands of developers.
  2. Shared vocabulary: "Use Observer here" instantly communicates a complex design idea.
  3. Avoid reinventing the wheel: Instead of designing from scratch, start with a known good solution.
  4. Better code: Patterns tend to produce more maintainable, flexible, and extensible code.
  5. Interview advantage: Design patterns are a core topic in software engineering interviews.

Common Patterns in Java Standard Libraryโ€‹

You don't need to look far to see patterns in action โ€” the Java standard library uses them everywhere:

PatternExample in Java
SingletonRuntime.getRuntime(), System.console()
Iteratorjava.util.Iterator interface
Observerjava.util.EventListener, java.util.Observable
Decoratorjava.io.InputStream wrapping chain
Factory MethodCalendar.getInstance(), NumberFormat.getInstance()
BuilderStringBuilder, java.util.stream.Stream.Builder
Strategyjava.util.Comparator
Adapterjava.util.Arrays.asList()
Proxyjava.lang.reflect.Proxy
Template Methodjava.io.InputStream.read()

Anti-Patterns: When Patterns Go Wrongโ€‹

Patterns are tools โ€” not mandatory laws. Using a pattern where it doesn't fit is called an anti-pattern:

  • Over-engineering: Applying complex patterns to simple problems.
  • Singleton abuse: Using Singleton for everything, creating hidden global state.
  • Pattern-matching for its own sake: Forcing a pattern just to sound sophisticated.

"A pattern is a solution to a problem in a context." โ€” GoF

Always ask: does this pattern solve a real problem in my code?


Real-World Analogyโ€‹

Design patterns are like furniture assembly instructions. IKEA has figured out the best way to assemble a bookshelf. You don't invent a new way โ€” you follow the proven pattern. But you still choose the wood color, size, and placement. Similarly, design patterns tell you the structure; you fill in the specifics for your application.


Code Exampleโ€‹

// Without patterns: tightly coupled, hard to extend
public class ReportGenerator {
public void generate(String type) {
if (type.equals("PDF")) {
// PDF generation logic
System.out.println("Generating PDF report...");
} else if (type.equals("EXCEL")) {
// Excel generation logic
System.out.println("Generating Excel report...");
}
// Adding a new type means modifying this class = bad!
}
}

// With Strategy pattern: open for extension, closed for modification
interface ReportStrategy {
void generate();
}

class PdfReport implements ReportStrategy {
@Override
public void generate() {
System.out.println("Generating PDF report...");
}
}

class ExcelReport implements ReportStrategy {
@Override
public void generate() {
System.out.println("Generating Excel report...");
}
}

class CsvReport implements ReportStrategy {
@Override
public void generate() {
System.out.println("Generating CSV report...");
}
}

class ReportGeneratorWithPattern {
private ReportStrategy strategy;

public ReportGeneratorWithPattern(ReportStrategy strategy) {
this.strategy = strategy;
}

public void setStrategy(ReportStrategy strategy) {
this.strategy = strategy;
}

public void generate() {
strategy.generate();
}
}

public class DesignPatternIntro {
public static void main(String[] args) {
ReportGeneratorWithPattern generator =
new ReportGeneratorWithPattern(new PdfReport());
generator.generate();

// Switch strategy at runtime โ€” no code change needed
generator.setStrategy(new ExcelReport());
generator.generate();

generator.setStrategy(new CsvReport());
generator.generate();
}
}

Outputโ€‹

Generating PDF report...
Generating Excel report...
Generating CSV report...

Common Mistakesโ€‹

  • โŒ Mistake: Memorizing patterns without understanding the problem they solve โ†’ โœ… Fix: Always learn the "problem context" first, then the solution.
  • โŒ Mistake: Applying patterns to every piece of code โ†’ โœ… Fix: Use patterns when they genuinely reduce complexity or improve flexibility. Simple code is often better.
  • โŒ Mistake: Thinking patterns are Java-specific โ†’ โœ… Fix: GoF patterns apply to any object-oriented language (Java, C++, Python, C#).

Best Practicesโ€‹

  • Learn the problem each pattern solves before memorizing its structure.
  • Recognize patterns in the Java standard library to see them in real use.
  • Don't force a pattern โ€” if the code is simple and clear without one, keep it simple.
  • Use patterns to communicate intent to other developers, not to show off knowledge.
  • Practice implementing each pattern from scratch at least once.

Interview Questionsโ€‹

Q: What is a design pattern?
A: A design pattern is a reusable, named solution template to a commonly occurring problem in software design. It's not code you copy-paste โ€” it's a blueprint you adapt. Patterns were popularized by the Gang of Four (GoF) in their 1994 book and are organized into three categories: Creational, Structural, and Behavioral.

Q: What are the three categories of GoF design patterns?
A: (1) Creational โ€” deal with object creation: Singleton, Factory, Builder, Prototype, Abstract Factory. (2) Structural โ€” deal with object composition: Adapter, Decorator, Proxy, Facade, Composite. (3) Behavioral โ€” deal with object communication: Observer, Strategy, Command, Iterator, Template Method.

Q: Can you give an example of a design pattern used in the Java standard library?
A: Many examples exist: java.io.InputStream and its wrappers (BufferedInputStream, DataInputStream) use the Decorator pattern. java.util.Iterator is an example of the Iterator pattern. Calendar.getInstance() is a Factory Method. java.lang.Runtime.getRuntime() is Singleton.


Quick Revisionโ€‹

โœ” Design patterns are reusable solution templates for recurring OOP design problems
โœ” Gang of Four (GoF) catalogued 23 patterns in their 1994 book
โœ” Creational: how objects are created (Singleton, Factory, Builder)
โœ” Structural: how objects are composed (Adapter, Decorator, Proxy)
โœ” Behavioral: how objects communicate (Observer, Strategy, Iterator)
โœ” Patterns are not algorithms โ€” they operate at the architectural/design level


  • Singleton Pattern (Lesson 2)
  • Factory Pattern (Lesson 3)
  • Strategy Pattern (Lesson 6)

Next Lessonโ€‹

Lesson 2 โ€” Singleton Pattern: Ensuring Only One Instance