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

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

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

目前已经更新到了:

  • MyBatis(正在更新)

基本介绍

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

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

具体如下图所示:
Java-18 深入浅出 MyBatis - 用到的设计模式 源码剖析 建造者模式、工厂模式-LMLPHP

建造者模式

概念介绍

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

简单案例

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

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

此时我们 :

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

编写代码

WzkComputer

@Data
@AllArgsConstructor
@NoArgsConstructor
public class WzkComputer {

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

}

WzkComputerBuilder

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

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,控制台输出结果如下:

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

对应的截图如下所示:
Java-18 深入浅出 MyBatis - 用到的设计模式 源码剖析 建造者模式、工厂模式-LMLPHP

MyBatis 的体现

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

Java-18 深入浅出 MyBatis - 用到的设计模式 源码剖析 建造者模式、工厂模式-LMLPHP
在 MyBatis 环境的初始化过程中,SqlSessionFactoryBuilder 会调用 XMLConfigBuilder 读取所有的 MyBatisMapConfig.xmk 和 所有的 mapper.xml 文件。

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 类根据不同的参数输入参数来构建,这么多的工作不是一个构造函数能够完成的。

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

工厂模式

概念介绍

在 MyBatis 中比如 SqlSessionFactory 使用的是工厂模式,该工厂没有那么复杂的逻辑,是一个简单工厂模式。
简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于创建型模式。
在简单工厂模式中,可以根据参数的不同返回不同类的实例,简单工厂模式专门定义了一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

简单案例

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

编写代码

WzkComputer

package icu.wzk.design.factory;

public abstract class WzkComputer {

    public abstract void start();

}

LenovoComputer

package icu.wzk.design.factory;

import icu.wzk.design.factory.WzkComputer;

public class LenovoComputer extends WzkComputer {

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

HpComputer

package icu.wzk.design.factory;

public class HpComputer extends WzkComputer {

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

ComputerFactory

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

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 的创建过程使用到了工厂模式。

Java-18 深入浅出 MyBatis - 用到的设计模式 源码剖析 建造者模式、工厂模式-LMLPHP
可以看到有很多的重载方法,DefaultSqlSessionFactory 中有默认的工厂实现。
Java-18 深入浅出 MyBatis - 用到的设计模式 源码剖析 建造者模式、工厂模式-LMLPHP

12-07 03:40