Mybatis 手撸专栏|第21章:Mybatis 框架源码10种设计模式分析

2023-11-14 09:43:37 浏览数 (1)

Mybatis 手撸专栏 第21章:Mybatis 框架源码10种设计模式分析

本文是《Mybatis 手撸专栏》系列的第21章,将深入探讨 Mybatis 框架源码中使用的10种设计模式。我们将一起通过代码分析和解释,了解这些设计模式在 Mybatis 中的运用,以及它们对框架的贡献。

1. 单例模式(Singleton)

单例模式是一种创建型设计模式,用于确保一个类只有一个实例,并提供对该实例的全局访问点。

在 Mybatis 框架中,SqlSessionFactory 类就是使用单例模式创建的。它负责创建和管理 SqlSession 对象,是整个 Mybatis 框架的核心。

以下是 SqlSessionFactory 类的单例实现:

代码语言:java复制
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 类的简化代码:

代码语言:java复制
public class SqlSessionFactoryBuilder {
    public SqlSessionFactory build(Configuration configuration) {
        // 构建 SqlSessionFactory 对象的逻辑
        
        return new SqlSessionFactory(configuration);
    }
}

通过使用工厂模式,Mybatis 将对象的创建过程与应用代码解耦,使得框架更加灵活和可扩展。

3. 代理模式(Proxy)

代理模式是一种结构型设计模式,用于控制对其他对象的访问。

在 Mybatis 框架中,MapperProxy 类就是使用代理模式实现的。它负责动态代理 Mapper 接口,并将方法调用转发给 SqlSession 对象来执行对数据库的操作。

以下是 MapperProxy 类的简化代码:

代码语言:java复制
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 类的简化代码:

代码语言:java复制
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 类的简化代码:

代码语言:java复制
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 类的简化代码:

代码语言:java复制
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 类的简化代码:

代码语言:java复制
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腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

0 人点赞