Fundamentals 12 min read

8 Essential Design Patterns Every Java Developer Should Master

This article introduces eight core design patterns—Singleton, Factory, Strategy, Proxy, Observer, Decorator, Template Method, and Builder—explaining their concepts, providing Java code examples, and showing typical JDK and Spring framework usages to help developers write cleaner, more maintainable code.

Su San Talks Tech
Su San Talks Tech
Su San Talks Tech
8 Essential Design Patterns Every Java Developer Should Master

Introduction

Design patterns are ubiquitous in software development, helping write more extensible and readable code.

This article presents eight commonly used design patterns with real‑world Java source examples and their typical usage in the JDK and Spring framework.

1. Singleton Pattern

The Singleton pattern ensures a class has only one instance, often used for shared resources such as configuration, cache, or thread pools.

Code implementation: double‑checked locking

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

JDK usage:

java.lang.Runtime.getRuntime()
java.util.logging.Logger

Spring usage: Spring beans are singleton by default; use @Scope("prototype") to change scope.

2. Factory Pattern

The Factory pattern encapsulates object‑creation logic, reducing coupling when instantiation is complex.

Code implementation: simple factory for payment systems

public class PaymentFactory {
    public static Payment createPayment(String type) {
        switch (type) {
            case "AliPay": return new AliPay();
            case "WeChatPay": return new WeChatPay();
            default: throw new IllegalArgumentException("Unknown payment type");
        }
    }
}

JDK usage:

java.util.Calendar.getInstance()
javax.xml.parsers.DocumentBuilderFactory.newInstance()

Spring usage: BeanFactory and ApplicationContext are examples of the factory pattern.

3. Strategy Pattern

The Strategy pattern encapsulates algorithms in separate classes and selects them at runtime.

Code implementation: promotion strategies

public interface PromotionStrategy {
    void applyPromotion();
}
public class DiscountStrategy implements PromotionStrategy {
    @Override
    public void applyPromotion() {
        System.out.println("Applying discount...");
    }
}
public class PromotionContext {
    private PromotionStrategy strategy;
    public PromotionContext(PromotionStrategy strategy) {
        this.strategy = strategy;
    }
    public void executePromotion() {
        strategy.applyPromotion();
    }
}

JDK usage: java.util.Comparator is a typical strategy.

Spring usage: Transaction management via TransactionManager uses strategy concepts.

4. Proxy Pattern

The Proxy pattern controls access to a target object, useful for permission checks, logging, etc.

Code implementation: static proxy

public interface Service {
    void execute();
}
public class RealService implements Service {
    @Override
    public void execute() {
        System.out.println("Executing real service...");
    }
}
public class ServiceProxy implements Service {
    private RealService realService;
    @Override
    public void execute() {
        System.out.println("Checking permissions...");
        if (realService == null) {
            realService = new RealService();
        }
        realService.execute();
    }
}

JDK usage:

Dynamic proxy: java.lang.reflect.Proxy RMI (remote method invocation)

Spring usage: AOP extensively uses the proxy pattern.

5. Observer Pattern

The Observer pattern defines a one‑to‑many dependency so that when one object changes, all its dependents are notified.

Code implementation: event notification

public interface Observer {
    void update(String message);
}
public class User implements Observer {
    private String name;
    public User(String name) { this.name = name; }
    @Override
    public void update(String message) {
        System.out.println(name + " received message: " + message);
    }
}
public class Weibo {
    private List<Observer> observers = new ArrayList<>();
    public void follow(Observer observer) { observers.add(observer); }
    public void post(String message) {
        for (Observer observer : observers) {
            observer.update(message);
        }
    }
}

JDK usage: java.util.Observer and

java.util.Observable
javax.swing.event.ChangeListener

Spring usage: ApplicationEvent and ApplicationListener implement the observer pattern.

6. Decorator Pattern

The Decorator pattern adds responsibilities to objects dynamically without modifying their structure.

Code implementation: coffee with add‑ons

public interface Coffee {
    String getDescription();
    double getCost();
}
public class SimpleCoffee implements Coffee {
    @Override
    public String getDescription() { return "Simple Coffee"; }
    @Override
    public double getCost() { return 5.0; }
}
public class MilkDecorator implements Coffee {
    private Coffee coffee;
    public MilkDecorator(Coffee coffee) { this.coffee = coffee; }
    @Override
    public String getDescription() { return coffee.getDescription() + ", Milk"; }
    @Override
    public double getCost() { return coffee.getCost() + 1.5; }
}

JDK usage: java.io.BufferedInputStream and java.io.BufferedOutputStream act as decorators.

Spring usage: BeanPostProcessor can modify bean behavior at runtime.

7. Template Method Pattern

The Template Method defines the skeleton of an algorithm, leaving concrete steps to subclasses.

Code implementation: task execution template

public abstract class Task {
    public final void execute() {
        init();
        doWork();
        cleanup();
    }
    protected abstract void init();
    protected abstract void doWork();
    protected void cleanup() {
        System.out.println("Default cleanup...");
    }
}
public class DataProcessingTask extends Task {
    @Override
    protected void init() {
        System.out.println("Initializing data...");
    }
    @Override
    protected void doWork() {
        System.out.println("Processing data...");
    }
}

JDK usage: java.util.AbstractList and java.util.AbstractMap follow this pattern.

Spring usage: JdbcTemplate and RestTemplate provide template implementations.

8. Builder Pattern

The Builder pattern constructs complex objects step by step, especially when many optional parameters exist.

Code implementation: HTTP request builder

public class HttpRequest {
    private String method;
    private String url;
    private String body;
    private HttpRequest(Builder builder) {
        this.method = builder.method;
        this.url = builder.url;
        this.body = builder.body;
    }
    public static class Builder {
        private String method;
        private String url;
        private String body;
        public Builder method(String method) { this.method = method; return this; }
        public Builder url(String url) { this.url = url; return this; }
        public Builder body(String body) { this.body = body; return this; }
        public HttpRequest build() { return new HttpRequest(this); }
    }
}

JDK usage: StringBuilder and Stream.Builder.

Spring usage: UriComponentsBuilder builds URIs.

Conclusion

These design patterns are widely applied in everyday development and are deeply reflected in both the JDK and Spring framework.

Understanding their essence and usage scenarios enables you to write more elegant and robust code.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Design PatternsJavaSingletonstrategyDecoratorFactoryObserverBuilder
Su San Talks Tech
Written by

Su San Talks Tech

Su San, former staff at several leading tech companies, is a top creator on Juejin and a premium creator on CSDN, and runs the free coding practice site www.susan.net.cn.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.