Comprehensive Guide to GoF Design Patterns in Java

Overview of Design Patterns

Design patterns represent reusable, time-tested solutions to recurring software engineering challenges. By categorizing these patterns, developers achieve cleaner, more maintainable, and loosely coupled code. The Gang of Four (GoF) defined 23 classic design patterns, classified into three functional categories:

  • Creational Patterns (5): Focused on object instantiation mechanisms.
  • Structural Patterns (7): Concerned with class and object composition.
  • Behavioral Patterns (11): Manage communication and responsibilities between objects.

Creational Patterns: Singleton

The Singleton pattern restricts a class to a single instance and provides a global access point. While several implementation strategies exist, the optimal choice depends on thread safety and performance requirements.

Thread-Safe Lazy Initialization with Double-Checked Locking

public class SingletonInstance {
    private static volatile SingletonInstance instance;

    private SingletonInstance() {}

    public static SingletonInstance getInstance() {
        if (instance == null) {
            synchronized (SingletonInstance.class) {
                if (instance == null) {
                    instance = new SingletonInstance();
                }
            }
        }
        return instance;
    }
}

Structural Patterns: Adapter

The Adapter pattern converts the interface of a class into another interface that clients expect. It enables classes with incompatible interfaces to work together.

Object Adapter Example

public class SystemAdapter implements TargetInterface {
    private final LegacySystem legacySystem;

    public SystemAdapter(LegacySystem legacySystem) {
        this.legacySystem = legacySystem;
    }

    @Override
    public void request() {
        legacySystem.legacyRequest();
    }
}

Behavioral Patterns: Strategy

The Strategy pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. It allows the algorithm to vary independently from the clients that use it.

Strategy Implementation

public interface SortingStrategy {
    void sort(int[] data);
}

public class QuickSort implements SortingStrategy {
    public void sort(int[] data) { /* Implementation */ }
}

public class SorterContext {
    private SortingStrategy strategy;

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

    public void executeSort(int[] data) {
        strategy.sort(data);
    }
}

Behavioral Patterns: Observer

The Observer pattern defines a one-to-many dependency between objects sothat when one object changes state, all its dependents are notified and updated automatically.

Observer Mechanism

public interface Observer {
    void update(String message);
}

public class Subject {
    private final List<Observer> observers = new ArrayList<>();

    public void attach(Observer o) { observers.add(o); }

    public void notifyObservers(String msg) {
        for (Observer o : observers) {
            o.update(msg);
        }
    }
}

Design patterns are not a "silver bullet"; they should be applied judiciously based on the specific architectural needs and complexity of the system.

Tags: java Design Patterns Software Architecture OOP

Posted on Sat, 29 Aug 2026 16:39:46 +0000 by dapuxter