Backend Development 13 min read

Understanding Simple Factory, Factory Method, Singleton, Adapter, Decorator, Observer, Strategy, and Template Method Patterns in Spring

This article explains how Spring implements classic design patterns—including Simple Factory via BeanFactory, Factory Method with FactoryBean, Singleton with double‑checked locking, Adapter through HandlerAdapter, Decorator via Wrapper classes, Observer in its event model, Strategy via the Resource interface, and Template Method in JdbcTemplate—providing clear examples and code snippets for each.

Architecture Digest
Architecture Digest
Architecture Digest
Understanding Simple Factory, Factory Method, Singleton, Adapter, Decorator, Observer, Strategy, and Template Method Patterns in Spring

Simple Factory pattern in Spring is realized through BeanFactory , which creates bean instances based on a unique identifier supplied at runtime.

Factory Method pattern is implemented via the FactoryBean interface; when getBean() is called, Spring invokes the bean's getObject() method and returns its result.

Spring beans are singleton by default. The getSingleton method in AbstractBeanFactory uses double‑checked locking to ensure a single instance per bean name.

public Object getSingleton(String beanName){
    // allow early reference
    return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                ObjectFactory
singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

Adapter pattern is embodied by Spring MVC's HandlerAdapter , which receives a handler from HandlerMapping and invokes the appropriate controller method, returning a ModelAndView .

Decorator pattern appears in Spring classes whose names contain Wrapper or Decorator , allowing dynamic addition of responsibilities without subclassing.

Observer pattern is used in Spring's event‑driven model. Core components include ApplicationEvent (the event), ApplicationListener (the listener), and ApplicationEventPublisher (the source).

public abstract class ApplicationEvent extends EventObject {
    private static final long serialVersionUID = 7099057708183571937L;
    private final long timestamp;
    public ApplicationEvent(Object source) {
        super(source);
        this.timestamp = System.currentTimeMillis();
    }
    public final long getTimestamp() {
        return this.timestamp;
    }
}
public interface ApplicationListener
extends EventListener {
    void onApplicationEvent(E event);
}
public interface ApplicationEventPublisher {
    void publishEvent(ApplicationEvent event);
}
public void publishEvent(ApplicationEvent event) {
    Assert.notNull(event, "Event must not be null");
    if (logger.isTraceEnabled()) {
        logger.trace("Publishing event in " + getDisplayName() + ": " + event);
    }
    getApplicationEventMulticaster().multicastEvent(event);
    if (this.parent != null) {
        this.parent.publishEvent(event);
    }
}

Strategy pattern is illustrated by Spring's Resource abstraction, which defines a common API for accessing various underlying resources (e.g., UrlResource , ClassPathResource , FileSystemResource , etc.).

Template Method pattern is pervasive in Spring; a prime example is JdbcTemplate , which defines a fixed algorithm skeleton for JDBC operations and delegates variable steps to callback interfaces.

public abstract class JdbcTemplate {
    public final Object execute(String sql) {
        Connection con = null;
        Statement stmt = null;
        try {
            con = getConnection();
            stmt = con.createStatement();
            Object retValue = executeWithStatement(stmt, sql);
            return retValue;
        } finally {
            closeStatement(stmt);
            releaseConnection(con);
        }
    }
    protected abstract Object executeWithStatement(Statement stmt, String sql);
}
public interface StatementCallback {
    Object doWithStatement(Statement stmt);
}
public class JdbcTemplate {
    public final Object execute(StatementCallback callback) {
        Connection con = null;
        Statement stmt = null;
        try {
            con = getConnection();
            stmt = con.createStatement();
            Object retValue = callback.doWithStatement(stmt);
            return retValue;
        } finally {
            closeStatement(stmt);
            releaseConnection(con);
        }
    }
    // other methods ...
}

These examples demonstrate how Spring leverages classic design patterns to achieve loose coupling, extensibility, and reusable infrastructure across its core container and various modules.

Design PatternsJavabackend developmentSpringDependency InjectionSingletonFactory Method
Architecture Digest
Written by

Architecture Digest

Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.

0 followers
Reader feedback

How this landed with the community

login 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.