Java-18 深入浅出 MyBatis - 用到的设计模式 源码剖析 建造者模式、工厂模式

点一下关注吧!!!非常感谢!!持续更新!!!

大数据篇正在更新!https://blog.csdn.net/w776341482/category_12713819.html

目前已经更新到了:

  • MyBatis(正在更新)

基本介绍

MyBatis 中用到了如下的设计模式:

  • 建造者模式:SqlSessionFactoryBuilder、Environment
  • 工厂方法模式:SqlSessionFactory、TransactionFactory、LogFactory
  • 单例模式:ErrorContext、LogFactory
  • 代理模式:MapperProxy、ConnectionLogger
  • 组合模式:SqlNode、ChooseSqlNode
  • 模板方法方式:BaseExecutor、SimpleExecutor
  • 适配器模式:Log
  • 装饰者模式:Cache
  • 迭代起模式:PropertyTokenizer

具体如下图所示:

建造者模式

概念介绍

该模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。它属于创建类模式,一般来说,如果一个对象的构建比较复杂,超出了构造函数所能包含的范围,就可以使用工厂模式和 Builder 模式,相对于工厂模式会产出一个完整的产品,Builder 应用与更加复杂的对象构建,甚至只会构建产品的一个部分。

简单来说,就是通过简单的对象来一步一步构建复杂的对象。

简单案例

比如要组装一台电脑,我们需要:

  • 主机
  • 显示器
  • 键盘
  • 鼠标
  • 音响

此时我们 :

  • 目标类
  • 构建类
  • 依次创建部件
  • 组装结果

编写代码

WzkComputer

java 复制代码
@Data
@AllArgsConstructor
@NoArgsConstructor
public class WzkComputer {

    private String displayer;
    private String mouse;
    private String keyword;
    private String sound;

}

WzkComputerBuilder

java 复制代码
package icu.wzk.design.builder;

import javafx.util.Builder;

public class WzkComputerBuilder {

    private WzkComputer wzkComputer = new WzkComputer();

    public WzkComputerBuilder installDisplay(String displayName) {
        wzkComputer.setDisplayer(displayName);
        return this;
    }

    public WzkComputerBuilder installMouse(String mouseName) {
        wzkComputer.setMouse(mouseName);
        return this;
    }

    public WzkComputerBuilder installKeyboard(String keyboardName) {
        wzkComputer.setKeyword(keyboardName);
        return this;
    }

    public WzkComputerBuilder installSound(String soundName) {
        wzkComputer.setSound(soundName);
        return this;
    }

    public WzkComputer build() {
        return wzkComputer;
    }
}

WzkBuilderTest

java 复制代码
package icu.wzk.design.builder;

public class WzkBuilderTest {

    public static void main(String[] args) {
        WzkComputer wzkComputer = new WzkComputerBuilder()
                .installDisplay("三星")
                .installMouse("罗技")
                .installKeyboard("罗技")
                .installSound("破喇叭")
                .build();
        System.out.println(wzkComputer);
    }

}

测试运行

执行上述的 WzkBuilderTest,控制台输出结果如下:

shell 复制代码
WzkComputer(displayer=三星, mouse=罗技, keyword=罗技, sound=破喇叭)
Process finished with exit code 0

对应的截图如下所示:

MyBatis 的体现

SqlSessionFactory 的构建过程:MyBatis 的初始化工作非常复杂,不是只用了一个构造函数就能搞定的,所以使用了建造者模式,使用了大量的 Builder,进行分层构造,核心对象是 Configuration,使用了 XMLConfigBuilder 来进行构造。

在 MyBatis 环境的初始化过程中,SqlSessionFactoryBuilder 会调用 XMLConfigBuilder 读取所有的 MyBatisMapConfig.xmk 和 所有的 mapper.xml 文件。

java 复制代码
private void parseConfiguration(XNode root) {
    try {
        // Issue #117: Read properties first
        // Parse <properties /> tag
        propertiesElement(root.evalNode("properties"));

        // Parse <settings /> tag
        Properties settings = settingsAsProperties(root.evalNode("settings"));

        // Load custom VFS implementation class
        loadCustomVfs(settings);

        // Parse <typeAliases /> tag
        typeAliasesElement(root.evalNode("typeAliases"));

        // Parse <plugins /> tag
        pluginElement(root.evalNode("plugins"));

        // Parse <objectFactory /> tag
        objectFactoryElement(root.evalNode("objectFactory"));

        // Parse <objectWrapperFactory /> tag
        objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));

        // Parse <reflectorFactory /> tag
        reflectorFactoryElement(root.evalNode("reflectorFactory"));

        // Set <settings /> to Configuration property
        settingsElement(settings);

        // Issue #631: Read it after objectFactory and objectWrapperFactory
        // Parse <environments /> tag
        environmentsElement(root.evalNode("environments"));

        // Parse <databaseIdProvider /> tag
        databaseIdProviderElement(root.evalNode("databaseIdProvider"));
    } catch (Exception e) {
        // Handle exceptions
        e.printStackTrace();
    }
}

其次,在 XMLConfigBuilder 在构建 Configuration 对象时,也会调用 XMLMapperBuilder 用于读取 Mapper 文件,而 XMLMapperBuilder 会使用 XMLStatementBuilder 来读取和 build 所有 SQL 语句。

可以看到 SqlSessionFactoryBuilder 类根据不同的参数输入参数来构建,这么多的工作不是一个构造函数能够完成的。

工厂模式

概念介绍

在 MyBatis 中比如 SqlSessionFactory 使用的是工厂模式,该工厂没有那么复杂的逻辑,是一个简单工厂模式。

简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于创建型模式。

在简单工厂模式中,可以根据参数的不同返回不同类的实例,简单工厂模式专门定义了一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

简单案例

假设有一个电脑的生产商,之前能生产联想电脑,随着业务的发展,现在可以生成惠普电脑了。我们可以用简单工厂来实现。

编写代码

WzkComputer

java 复制代码
package icu.wzk.design.factory;

public abstract class WzkComputer {

    public abstract void start();

}

LenovoComputer

java 复制代码
package icu.wzk.design.factory;

import icu.wzk.design.factory.WzkComputer;

public class LenovoComputer extends WzkComputer {

    @Override
    public void start() {
        System.out.println("生产联想电脑");
    }
}

HpComputer

java 复制代码
package icu.wzk.design.factory;

public class HpComputer extends WzkComputer {

    @Override
    public void start() {
        System.out.println("生产惠普电脑");
    }
}

ComputerFactory

java 复制代码
package icu.wzk.design.factory;

import icu.wzk.design.factory.WzkComputer;

public class ComputerFactory {

    public static WzkComputer createComputer(String type) {
        switch (type) {
            case "lenovo":
                return new LenovoComputer();
            case "hp":
                return new HpComputer();
            default:
                throw new IllegalArgumentException("Invalid computer type: " + type);
        }
    }

}

WzkComputerTest

java 复制代码
package icu.wzk.design.factory;

public class WzkComputerTest {

    public static void main(String[] args) {
        ComputerFactory.createComputer("lenovo").start();
        ComputerFactory.createComputer("hp").start();
    }

}

测试运行

控制台输出的内容如下所示:

MyBatis 的体现

MyBatis 中执行 SQL 语句,获取 Mappers,管理事务的核心接口 SqlSession 的创建过程使用到了工厂模式。

可以看到有很多的重载方法,DefaultSqlSessionFactory 中有默认的工厂实现。

相关推荐
掘金-我是哪吒2 分钟前
分布式微服务系统架构第156集:JavaPlus技术文档平台日更-Java线程池使用指南
java·分布式·微服务·云原生·架构
亲爱的非洲野猪28 分钟前
Kafka消息积压的多维度解决方案:超越简单扩容的完整策略
java·分布式·中间件·kafka
wfsm30 分钟前
spring事件使用
java·后端·spring
微风粼粼1 小时前
程序员在线接单
java·jvm·后端·python·eclipse·tomcat·dubbo
缘来是庄1 小时前
设计模式之中介者模式
java·设计模式·中介者模式
rebel1 小时前
若依框架整合 CXF 实现 WebService 改造流程(后端)
java·后端
代码的余温3 小时前
5种高效解决Maven依赖冲突的方法
java·maven
慕y2743 小时前
Java学习第十六部分——JUnit框架
java·开发语言·学习
paishishaba3 小时前
Maven
java·maven
张人玉3 小时前
C# 常量与变量
java·算法·c#