Mybatis 手撸专栏 第21章:Mybatis 框架源码10种设计模式分析
本文是《Mybatis 手撸专栏》系列的第21章,将深入探讨 Mybatis 框架源码中使用的10种设计模式。我们将一起通过代码分析和解释,了解这些设计模式在 Mybatis 中的运用,以及它们对框架的贡献。
1. 单例模式(Singleton)
单例模式是一种创建型设计模式,用于确保一个类只有一个实例,并提供对该实例的全局访问点。
在 Mybatis 框架中,SqlSessionFactory
类就是使用单例模式创建的。它负责创建和管理 SqlSession
对象,是整个 Mybatis 框架的核心。
以下是 SqlSessionFactory
类的单例实现:
public class SqlSessionFactory {
private static SqlSessionFactory instance;
private SqlSessionFactory() {
// 私有构造函数,防止外部实例化
}
public static synchronized SqlSessionFactory getInstance() {
if (instance == null) {
instance = new SqlSessionFactory();
}
return instance;
}
}
通过使用 getInstance
方法获取 SqlSessionFactory
的实例,我们可以确保在整个应用程序中只存在一个 SqlSessionFactory
对象。
2. 工厂模式(Factory)
工厂模式是一种创建型设计模式,用于将对象的创建过程封装在一个工厂类中,从而根据不同的条件创建具体的对象实例。
在 Mybatis 框架中,SqlSessionFactoryBuilder
类就是使用工厂模式创建的。它负责解析配置文件,并根据配置信息创建 SqlSessionFactory
对象。
以下是 SqlSessionFactoryBuilder
类的简化代码:
public class SqlSessionFactoryBuilder {
public SqlSessionFactory build(Configuration configuration) {
// 构建 SqlSessionFactory 对象的逻辑
return new SqlSessionFactory(configuration);
}
}
通过使用工厂模式,Mybatis 将对象的创建过程与应用代码解耦,使得框架更加灵活和可扩展。
3. 代理模式(Proxy)
代理模式是一种结构型设计模式,用于控制对其他对象的访问。
在 Mybatis 框架中,MapperProxy
类就是使用代理模式实现的。它负责动态代理 Mapper
接口,并将方法调用转发给 SqlSession
对象来执行对数据库的操作。
以下是 MapperProxy
类的简化代码:
public class MapperProxy implements InvocationHandler {
private SqlSession sqlSession;
public MapperProxy(SqlSession sqlSession) {
this.sqlSession = sqlSession;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 方法调用的逻辑
return sqlSession.selectOne(method.getName(), args[0]);
}
}
通过使用代理模式,Mybatis 实现了动态代理 Mapper
接口,并将具体的方法调用转发给 SqlSession
对象,从而实现了和数据库的交互。
4. 观察者模式(Observer)
观察者模式是一种行为型设计模式,用于定义对象之间的一对多依赖关系,当一个对象的状态发生改变时,其所有依赖对象都会收到通知并自动更新。
在 Mybatis 框架中,Executor
类就是使用观察者模式实现的。它负责执行数据库操作并在执行完成后通知注册的监听器。
以下是 Executor
类的简化代码:
public class Executor {
private List<ExecutorListener> listeners = new ArrayList<>();
public void execute() {
// 执行数据库操作的逻辑
// 执行完毕后通知监听器
for (ExecutorListener listener : listeners) {
listener.onExecuteComplete();
}
}
public void addListener(ExecutorListener listener) {
listeners.add(listener);
}
}
通过使用观察者模式,Executor
类在执行完数据库操作后,会自动通知所有注册的监听器,让它们进行相应的处理。
5. 策略模式(Strategy)
策略模式是一种行为型设计模式,用于定义一系列算法并将其封装起来,使得它们可以互相替换,从而使得算法的变化独立于调用者。
在 Mybatis 框架中,StatementHandler
类就是使用策略模式实现的。它负责处理不同类型的 SQL 语句,并将其封装成不同的策略。
以下是 StatementHandler
类的简化代码:
public class StatementHandler {
private StatementStrategy strategy;
public StatementHandler(StatementStrategy strategy) {
this.strategy = strategy;
}
public void handleStatement() {
// 使用策略对象处理 SQL 语句
strategy.handleStatement();
}
}
public interface StatementStrategy {
void handleStatement();
}
通过使用策略模式,StatementHandler
类可以根据需要动态切换不同的策略,从而处理不同类型的 SQL 语句。
6. 模板方法模式(Template Method)
模板方法模式是一种行为型设计模式,用于定义一个操作的骨架,将一些步骤的具体实现延迟到子类中。
在 Mybatis 框架中,BaseExecutor
类就是使用模板方法模式实现的。它定义了数据库操作的流程和骨架,并将具体的执行细节交给子类去实现。
以下是 BaseExecutor
类的简化代码:
public abstract class BaseExecutor implements Executor {
public <T> List<T> query(String sql) {
// 查询操作的通用流程
// 具体的查询细节由子类实现
return doQuery(sql);
}
protected abstract <T> List<T> doQuery(String sql);
}
通过使用模板方法模式,BaseExecutor
类定义了数据库操作的通用流程,而具体的查询细节则由子类去实现。
7. 装饰者模式(Decorator)
装饰者模式是一种结构型设计模式,用于动态地给对象添加额外的功能,而不需要修改其原始类。
在 Mybatis 框架中,ResultSetHandler
类就是使用装饰者模式实现的。它负责处理查询结果集,并在其基础上添加了缓存功能。
以下是 ResultSetHandler
类的简化代码:
public class ResultSetHandlerDecorator implements ResultSetHandler {
private ResultSetHandler delegate;
public ResultSetHandlerDecorator(ResultSetHandler delegate) {
this.delegate = delegate;
}
@Override
public <T> List<T> handleResultSet(ResultSet resultSet) {
// 添加缓存功能
if (isCacheEnabled()) {
// 在委托对象的基础上进行缓存操作
}
// 调用委托对象的方法处理结果集
return delegate.handleResultSet(resultSet);
}
}
通过使用装饰者模式,ResultSetHandlerDecorator
类在处理结果集之前加上了缓存功能,而无需修改原始的 ResultSetHandler
类。
8. 适配器模式(Adapter)
适配器模式是一种结构型设计模式,它允许将一个类的接口转换成客户端所期望的另一个接口。通过适配器模式,不需要修改现有的类,就可以使得不兼容的类可以一起工作。
在 Android 开发中,适配器模式非常常见,特别是在 RecyclerView 和 ListView 中。适配器通常将数据和视图进行适配,以便在列表中显示。
以下是一个用于 RecyclerView 的适配器的简化示例:
代码语言:java复制public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private List<String> data;
public MyAdapter(List<String> data) {
this.data = data;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// 创建视图并返回包含视图的 ViewHolder
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
// 绑定数据到 ViewHolder 的视图上
String item = data.get(position);
holder.textView.setText(item);
}
@Override
public int getItemCount() {
return data.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
public TextView textView;
public MyViewHolder(View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.text_view);
}
}
}
在该示例中,MyAdapter
是一个适配器,负责将数据源 data
中的数据适配到 RecyclerView 的列表项视图中。通过适配器模式,我们可以轻松地在 RecyclerView 中显示我们的数据。
9. 代理模式(Proxy)
代理模式是一种结构型设计模式,它为其他对象提供一个代理,以控制对这个对象的访问。通过使用代理模式,我们可以在访问对象之前或之后执行额外的操作。
在软件开发中,代理模式的应用非常广泛。例如,为了实现网络安全性,我们可能使用代理模式来限制对某些敏感资源的访问。
以下是一个简单的示例来说明代理模式的使用:
代码语言:java复制public interface Image {
void display();
}
public class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadFromDisk();
}
private void loadFromDisk() {
// 从硬盘加载图像
}
@Override
public void display() {
// 显示图像
}
}
public class ProxyImage implements Image {
private String filename;
private RealImage realImage;
public ProxyImage(String filename) {
this.filename = filename;
}
@Override
public void display() {
if (realImage == null) {
realImage = new RealImage(filename);
}
realImage.display();
}
}
在该示例中,Image
接口定义了图像的显示方法,RealImage
类是真正的图像类,负责从硬盘加载图像并进行显示。ProxyImage
类是代理类,它控制对 RealImage
对象的访问。只有在需要显示图像时,代理才会创建并使用真实的图像。
通过使用代理模式,我们可以控制对敏感资源(如图像)的访问,并在必要时进行额外的处理。
10. 外观模式(Facade)
外观模式是一种结构型设计模式,它提供了一个统一的接口,用于访问子系统中的一组接口。通过使用外观模式,我们可以简化复杂系统的使用,并隐藏系统的复杂性。
在 Android 开发中,外观模式经常被用于封装底层的系统调用,以便开发者可以更方便地使用一些功能强大的功能。
以下是一个简化的示例来说明外观模式的使用:
代码语言:java复制public class Camera {
public void turnOn() {
// 打开相机
}
public void turnOff() {
// 关闭相机
}
public void takePhoto() {
// 拍照
}
}
public class Gallery {
public void open() {
// 打开相册
}
public void browsePhotos() {
// 浏览照片
}
public void deletePhoto() {
// 删除照片
}
}
public class Phone {
private Camera camera;
private Gallery gallery;
public Phone() {
camera = new Camera();
gallery = new Gallery();
}
public void takePhoto() {
camera.turnOn();
camera.takePhoto();
camera.turnOff();
}
public void browsePhotos() {
gallery.open();
gallery.browsePhotos();
}
}
在该示例中,Phone
类作为外观类,提供了一个简化的接口来使用相机和相册。通过使用外观模式,我们可以不必关心相机和相册的复杂操作,只需要调用外观类提供的方法即可。
希望这篇文章帮助您更好地理解 Mybatis 框架中的设计模式应用。如果您还有任何问题,请随时向我提问。感谢阅读!
代码语言:java复制public class Demo {
public static void main(String[] args) {
System.out.println("Hello, Mybatis!");
}
}
代码参考来源:Mybatis 框架源码 Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!