How MyBatis Implements 9 Classic Design Patterns – A Deep Dive
This article explores how MyBatis applies 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 explanations and concrete code snippets to deepen developers' understanding of real‑world pattern usage.
Although there are 26 classic design patterns, most developers only know them conceptually; MyBatis, a popular Java persistence framework, embeds many of these patterns in its source code. Studying the implementation provides a practical view of how patterns solve real problems.
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. In MyBatis, classes such as SqlSessionFactoryBuilder, XMLConfigBuilder, XMLMapperBuilder, XMLStatementBuilder and CacheBuilder follow this pattern. During initialization, SqlSessionFactoryBuilder reads configuration files, builds a Configuration object, and then creates a SqlSessionFactory. The builders perform extensive parsing, reflection, and caching that would be unsuitable for a single constructor.
2. Factory Pattern
MyBatis uses the Factory pattern for objects like SqlSessionFactory, ObjectFactory and MapperProxyFactory. SqlSessionFactory is created via a simple factory method that selects the appropriate implementation based on parameters. The source shows the core method openSessionFromDataSource which obtains an Environment, creates a Transaction, builds an Executor, and finally returns a DefaultSqlSession. The factory produces not a single product but a family of Log implementations (e.g., Log4jImpl, Slf4jImpl) via a Constructor<? extends Log> reference.
3. Singleton Pattern
Singleton ensures a class has only one instance. MyBatis applies it in ErrorContext and LogFactory. ErrorContext uses a ThreadLocal<ErrorContext> to provide a per‑thread singleton that records error information. The instance() method lazily creates the object if absent and returns the same instance for the thread.
4. Proxy Pattern
Proxy is the core of MyBatis' mapper mechanism. Developers write only a mapper interface; MyBatis generates a dynamic proxy that forwards method calls to MapperProxy.invoke. The proxy creates a MapperMethod which executes the SQL via SqlSession, Executor, and statement preparation. The source includes the MapperProxyFactory and MapperProxy implementations, showing how Proxy.newProxyInstance is used to create the proxy object.
5. Composite Pattern
Composite treats individual objects and compositions uniformly. MyBatis builds a tree of SqlNode objects (e.g., TrimSqlNode, IfSqlNode, TextSqlNode) to represent dynamic SQL. Each node implements boolean apply(DynamicContext). Leaf nodes like TextSqlNode directly append SQL fragments, while composite nodes like IfSqlNode evaluate a condition before delegating to child nodes, enabling recursive SQL generation.
6. Template Method Pattern
Template Method defines the skeleton of an algorithm in a base class while allowing subclasses to override specific steps. BaseExecutor follows this pattern: it implements the overall execution flow and declares abstract methods such as doUpdate, doFlushStatements, and doQuery. Subclasses SimpleExecutor, ReuseExecutor, and BatchExecutor provide concrete strategies for statement handling, reuse, and batch processing.
7. Adapter Pattern
Adapter converts one interface to another. MyBatis defines a generic Log interface and provides adapters for various logging frameworks (Log4j, SLF4J, Commons‑Logging, etc.). Each adapter implements Log and delegates calls to the underlying framework’s logger, allowing MyBatis to remain independent of any specific logging library.
8. Decorator Pattern
Decorator adds responsibilities to objects dynamically. MyBatis cache implementation uses a core PerpetualCache wrapped by a chain of decorators (e.g., FifoCache, LruCache, LoggingCache, SerializedCache, ScheduledCache, SoftCache, SynchronizedCache, WeakCache, and TransactionalCache). The decorator chain is assembled automatically based on configuration, providing features such as eviction policies, logging, serialization, and transaction‑aware caching.
9. Iterator Pattern
Iterator provides a way to access elements of a collection without exposing its internal structure. MyBatis uses PropertyTokenizer, which implements Iterator<PropertyTokenizer>, to parse property strings (e.g., "user.address[0].street"). It splits the string into name, index, and children, allowing sequential traversal of nested property tokens.
The article includes numerous code excerpts (shown in <pre><code>... </pre> blocks) and diagrams that illustrate each pattern’s role within MyBatis.
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.
Senior Brother's Insights
A public account focused on workplace, career growth, team management, and self-improvement. The author is the writer of books including 'SpringBoot Technology Insider' and 'Drools 8 Rule Engine: Core Technology and Practice'.
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.
