铁锤的IT奇妙探险 Java Back-End Coder

设计模式之建造者模式

2020-07-03


建造者模式在Mybatis中的典型应用即SqlSessionFactoryBuilder,让我们来了解到底什么是建造者模式。

建造者模式

角色

  1. Builder(抽象建造者):它为创建一个产品Product对象的各个部件指定抽象接口,在该接口中一般声明两类方法,一类方法是buildPartX(),它们用于创建复杂对象的各个部件;另一类方法是getResult(),它们用于返回复杂对象。Builder既可以是抽象类,也可以是接口。
  2. ConcreteBuilder(具体建造者):它实现了Builder接口,实现各个部件的具体构造和装配方法,定义并明确它所创建的复杂对象,也可以提供一个方法返回创建好的复杂产品对象。
  3. Product(产品角色):它是被构建的复杂对象,包含多个组成部件,具体建造者创建该产品的内部表示并定义它的装配过程。
  4. Director(指挥者):指挥者又称为导演类,它负责安排复杂对象的建造次序。客户端一般只需要与指挥者进行交互,在客户端确定具体建造者的类型,并实例化具体建造者对象(也可以通过配置文件和反射机制),然后通过指挥者类的构造函数或者Setter方法将该对象传入指挥者类中。

产品角色

public class Computer {
    private String brand;
    private String cpu;
    private String mainBoard;
    // 省略 getter, setter, toString
}

抽象建造者 builder

public abstract class Builder {
    protected Computer computer = new Computer();

    public abstract void buildBrand();
    public abstract void buildCPU();
    public abstract void buildMainBoard();
    public Computer createComputer() {
        return computer;
    }
}

具体建造者 DellComputerBuilder,ASUSComputerBuilder,分别建造戴尔电脑和华硕电脑

public class DellComputerBuilder extends Builder {
    @Override
    public void buildBrand() {
        computer.setBrand("戴尔电脑");
    }
    @Override
    public void buildCPU() {
        computer.setCpu("i5-8300H 四核");
    }
    @Override
    public void buildMainBoard() {
        computer.setMainBoard("戴尔主板");
    }
}

public class ASUSComputerBuilder extends Builder{
    @Override
    public void buildBrand() {
        computer.setBrand("华硕电脑");
    }
    @Override
    public void buildCPU() {
        computer.setCpu("Intel 第8代 酷睿");
    }
    @Override
    public void buildMainBoard() {
        computer.setMainBoard("华硕主板");
    }
}

指挥者 ComputerDirector,指挥构建过程

public class ComputerDirector {
    public Computer construct(Builder builder) {
        // 逐步构建复杂产品对象
        Computer computer;
        builder.buildBrand();
        builder.buildCPU();
        builder.buildMainBoard();
        computer = builder.createComputer();
        return computer;
    }
}

可以通过反射机制和配置文件配合,创建具体建造者对象

public class Test {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        ComputerDirector director = new ComputerDirector();

        // 从数据库或者配置文件中读取具体建造者类名
        Class c = Class.forName("com.designpattern.ASUSComputerBuilder");
        Builder asusBuilder = (Builder) c.newInstance();
        Computer asusComputer = director.construct(asusBuilder);
        System.out.println(asusComputer.toString());
    }
}
SqlSessionFactoryBuilder

典型代表是SqlSessionFactoryBuilder,在 SqlSessionFactoryBuilder 中构建 SqlSessionFactory 对象的过程是这样的,首先需要通过XMLConfigBuilder 对象读取并解析 XML 的配置文件,然后再将读取到的配置信息存入到 Configuration 类中,然后再通过 build方法生成我们需要的DefaultSqlSessionFactory对象。

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
        XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
        //调用下面的build方法构建
        return build(parser.parse());
    } catch (Exception e) {
        throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    } finally {
        ErrorContext.instance().reset();
        try {
        inputStream.close();
        } catch (IOException e) {
        // Intentionally ignore. Prefer previous error.
        }
    }
}
public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
}

Similar Posts

Comments