MyBatis 是一个流行的 Java 持久层框架,它通过使用设计模式来提高代码的灵活性、可维护性和可扩展性。以下是 MyBatis 中常见的 9 种设计模式的全面剖析,包括代码示例和它们对我们工作或学习的启发。
1. 工厂模式(Factory Pattern)
定义:定义创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
应用示例 : 在 MyBatis 中,SqlSessionFactory
是通过工厂模式创建的。SqlSessionFactoryBuilder
是一个工厂类,它负责构建 SqlSessionFactory
实例。
java
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
启发:
- 在实际开发中,使用工厂模式可以避免硬编码对象的创建逻辑,使得代码更加灵活和可维护。
2. 单例模式(Singleton Pattern)
定义:保证一个类只有一个实例,并提供一个全局访问点。
应用示例 : SqlSessionFactory
是一个典型的单例。每个 MyBatis 应用通常只需要一个 SqlSessionFactory
实例。
java
public class SqlSessionFactoryBuilder {
private static SqlSessionFactory instance;
public static synchronized SqlSessionFactory build(InputStream inputStream) {
if (instance == null) {
instance = new SqlSessionFactory(new Configuration(inputStream));
}
return instance;
}
}
启发:
- 单例模式确保了资源的共享和一致性,适用于需要全局访问点的场景。
3. 建造者模式(Builder Pattern)
定义:将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。
应用示例 : SqlSessionFactoryBuilder
使用建造者模式构建 SqlSessionFactory
。
java
public class SqlSessionFactoryBuilder {
private Configuration configuration;
public SqlSessionFactoryBuilder(Configuration configuration) {
this.configuration = configuration;
}
public SqlSessionFactory build() {
return new SqlSessionFactory(configuration);
}
}
启发:
- 建造者模式使得对象的构建过程更加清晰和灵活,适用于创建复杂对象的场景。
4. 原型模式(Prototype Pattern)
定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
应用示例: 虽然 MyBatis 没有直接使用原型模式,但可以通过复制 SQL 语句模板来实现类似功能。
java
public class SqlStatement {
private String sql;
public SqlStatement(String sql) {
this.sql = sql;
}
public SqlStatement copy() {
return new SqlStatement(this.sql);
}
}
启发:
- 原型模式可以快速复制对象,适用于需要频繁创建相似对象的场景。
5. 适配器模式(Adapter Pattern)
定义:将一个类的接口转换成客户端所期待的另一种接口。
应用示例 : MapperProxy
是一个适配器,它将 Mapper
接口的方法调用适配到实际的 SQL 执行过程。
java
public class MapperProxy<T> implements InvocationHandler {
private final SqlSession sqlSession;
private final Class<T> mapperInterface;
public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface) {
this.sqlSession = sqlSession;
this.mapperInterface = mapperInterface;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.isDefault()) {
return invokeDefaultMethod(proxy, method, args);
}
return sqlSession.selectOne(method.getName(), args[0]);
}
private Object invokeDefaultMethod(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(this, args);
}
}
启发:
- 适配器模式可以解决接口不兼容的问题,使得不同接口的对象可以协同工作。
6. 装饰器模式(Decorator Pattern)
定义:动态地给一个对象添加额外的职责。
应用示例 : MyBatis 的 Plugin
机制使用装饰器模式,可以在运行时动态地添加插件。
java
public interface Plugin {
Object intercept(Invocation invocation) throws Throwable;
default Object plugin(Object target) {
return Plugin.wrap(target, this);
}
static Object wrap(Object target, Plugin plugin) {
if (target instanceof Executor) {
return new ExecutorProxy(target, plugin);
}
return null;
}
}
启发:
- 装饰器模式可以在不修改原有代码的情况下增强对象的功能,提高代码的可扩展性。
7. 观察者模式(Observer Pattern)
定义:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。
应用示例 : MyBatis 的 Executor
在执行 SQL 时,会通知相关的 Interceptor
进行处理。
java
public interface Interceptor {
Object intercept(Invocation invocation) throws Throwable;
default Object plugin(Object target) {
return Plugin.wrap(target, this);
}
static Object wrap(Object target, Interceptor interceptor) {
if (target instanceof Executor) {
return new ExecutorProxy(target, interceptor);
}
return null;
}
}
启发:
- 观察者模式可以实现对象间的解耦,使得一个对象的状态变化可以自动通知其他依赖对象。
8. 代理模式(Proxy Pattern)
定义:为其他对象提供一种代理以控制对这个对象的访问。
应用示例 : MapperProxy
是一个代理,它将 Mapper
接口的方法调用代理到实际的 SQL 执行过程。
java
public class MapperProxy<T> implements InvocationHandler {
private final SqlSession sqlSession;
private final Class<T> mapperInterface;
public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface) {
this.sqlSession = sqlSession;
this.mapperInterface = mapperInterface;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.isDefault()) {
return invokeDefaultMethod(proxy, method, args);
}
return sqlSession.selectOne(method.getName(), args[0]);
}
private Object invokeDefaultMethod(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(this, args);
}
}
启发:
- 代理模式可以控制对对象的访问,增加额外的处理逻辑,提高系统的安全性和灵活性。
9. 命令模式(Command Pattern)
定义:将一个请求或操作封装为一个对象,从而使用户可用不同的请求、队列或日志请求来参数化其他对象。
应用示例 : MyBatis 的 Executor
使用命令模式,每个 SQL 执行请求都被封装为一个 SqlCommand
对象。
java
public interface SqlCommand {
String getSql();
Integer getUpdateCount();
boolean isSelect();
void clear();
}
启发:
- 命令模式可以将请求封装为对象,使得请求的发送者和接收者解耦,提高系统的灵活性和可扩展性。
对工作或学习的启发
- 提高代码的可维护性:通过使用设计模式,代码结构更加清晰,易于理解和维护。
- 增强代码的可扩展性:设计模式使得在不修改原有代码的情况下,可以灵活地扩展功能。
- 解耦和复用:设计模式有助于将系统的不同部分解耦,提高代码的复用性。
- 应对复杂性:在面对复杂的系统设计时,设计模式提供了一种结构化的方法来处理复杂性。
- 促进团队协作:设计模式作为一种通用语言,有助于团队成员之间的沟通和协作。
通过学习和应用这些设计模式,可以更有效地解决实际问题,提高软件的质量和性能。