How MyBatis Leverages 9 Classic Design Patterns in Its Core
This article explores how MyBatis implements nine fundamental design patterns—including Builder, Factory, Singleton, Proxy, Composite, Template Method, Adapter, Decorator, and Iterator—by examining its source code, illustrating each pattern with concrete classes, code snippets, and diagrams to deepen developers' understanding of design patterns in practice.
Although most developers only know the 26 classic design patterns at a conceptual level, MyBatis’s source code applies many of them, making it an excellent case study for deeper learning.
MyBatis uses at least the following patterns:
Builder Pattern : e.g., SqlSessionFactoryBuilder, XMLConfigBuilder, XMLMapperBuilder, XMLStatementBuilder, CacheBuilder.
Factory Pattern : e.g., SqlSessionFactory, ObjectFactory, MapperProxyFactory.
Singleton Pattern : e.g., ErrorContext, LogFactory.
Proxy Pattern : core of MyBatis, e.g., MapperProxy, ConnectionLogger, dynamic proxies via JDK or CGLIB.
Composite Pattern : e.g., SqlNode hierarchy such as ChooseSqlNode.
Template Method Pattern : e.g., BaseExecutor defines the skeleton of SQL execution, delegating specific steps to subclasses.
Adapter Pattern : MyBatis’s logging abstraction adapts various logging frameworks (Log4j, SLF4J, etc.).
Decorator Pattern : cache implementations are layered with decorators like FifoCache, LruCache, LoggingCache, etc.
Iterator Pattern : e.g., PropertyTokenizer implements Iterator to traverse property strings.
1. Builder Pattern
The Builder pattern separates the construction of a complex object from its representation, allowing the same construction process to create different representations. MyBatis uses builders to read configuration files, parse XML, and assemble the Configuration object, which is then used to build a SqlSessionFactory.
Key builder classes have methods prefixed with build, such as those in SqlSessionFactoryBuilder that construct the factory based on input parameters.
2. Factory Pattern
MyBatis’s SqlSessionFactory is created via a simple factory. The factory method returns different instances based on configuration parameters, encapsulating the creation logic.
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { ... }The method obtains a Transaction, creates an Executor, and finally builds a SqlSession.
3. Singleton Pattern
Singleton ensures a class has only one instance. MyBatis uses it for ErrorContext (thread‑local singleton) and LogFactory (global singleton for logging).
public class ErrorContext { private static final ThreadLocal<ErrorContext> LOCAL = new ThreadLocal<>(); private ErrorContext() {} public static ErrorContext instance() { ... } }4. Proxy Pattern
The proxy pattern is the core of MyBatis: developers write only mapper interfaces, and MyBatis generates proxy instances that delegate method calls to the underlying SqlSession and Executor.
public class MapperProxyFactory<T> { public T newInstance(SqlSession sqlSession) { MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache); return (T) Proxy.newProxyInstance(...); } }5. Composite Pattern
MyBatis builds a tree of SqlNode objects (e.g., ChooseSqlNode, IfSqlNode) to represent dynamic SQL. Each node implements SqlNode.apply, allowing recursive processing of the tree.
public interface SqlNode { boolean apply(DynamicContext context); }6. Template Method Pattern
BaseExecutordefines the skeleton of SQL execution, while subclasses ( SimpleExecutor, ReuseExecutor, BatchExecutor) implement the abstract steps such as doUpdate, doQuery, and doFlushStatements.
protected abstract int doUpdate(MappedStatement ms, Object parameter) throws SQLException;7. Adapter Pattern
The logging abstraction adapts various logging frameworks (Log4j, SLF4J, etc.) to a common Log interface. Each implementation delegates calls to the underlying framework.
public class Log4jImpl implements Log { private Logger log; public void debug(String s) { log.debug(s); } ... }8. Decorator Pattern
MyBatis cache uses a series of decorators (e.g., FifoCache, LruCache, LoggingCache) that wrap a core PerpetualCache to add eviction policies, logging, serialization, etc.
9. Iterator Pattern
PropertyTokenizerimplements Iterator to parse property strings, providing hasNext, next, and remove (unsupported) methods.
public class PropertyTokenizer implements Iterator<PropertyTokenizer> { public boolean hasNext() { return children != null; } public PropertyTokenizer next() { return new PropertyTokenizer(children); } }Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Interview Crash Guide
Dedicated to sharing Java interview Q&A; follow and reply "java" to receive a free premium Java interview guide.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
