八吨车 记录所学,在校大二,软件工程,欢迎一起交流

建造者模式及在源码中的实践

建造者模式

用多个简单的对象创建一个复杂的对象,将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。
在这里插入图片描述
建造者模式在设计时有四种角色:
1.Builder:复杂产品对象的抽象接口
2.ConcreteBuilder:Builder的实现类,主要定义装配流程
3.Director:构造一个使用Builder抽象接口的对象
4.Product:表示被构造的复杂对象。ConcreteBuilder定义了该复杂对象的装配流程,而Product定义了该复杂对象的结构和内部表示。

建造者抽象类

public abstract class Builder {
    public abstract void buildCPU(String cpu);
    public abstract void buildMainBoard(String mainBoard);
    public abstract void buildHardDisk(String hardDisk);
    public abstract void buildDisplayCard(String displayCard);
    public abstract void buildPower(String power);
    public abstract void buildMemory(String memory);

    public abstract Computer createComputer();
    
}

具体建造者类

public class ActualBuilder extends Builder {
    private Computer computer = new Computer();

    @Override
    public void buildCPU(String cpu) {
        computer.setCpu(cpu);
    }

    @Override
    public void buildMainBoard(String mainBoard) {
        computer.setMainBoard(mainBoard);
    }

    @Override
    public void buildHardDisk(String hardDisk) {
        computer.setHardDisk(hardDisk);
    }

    @Override
    public void buildDisplayCard(String displayCard) {
        computer.setDisplayCard(displayCard);
    }

    @Override
    public void buildPower(String power) {
        computer.setPower(power);
    }

    @Override
    public void buildMemory(String memory) {
        computer.setMemory(memory);
    }

    @Override
    public Computer createComputer() {
        return computer;
    }
}

复杂对象

public class Computer {
    private String cpu;
    private String mainBoard;
    private String hardDisk;
    private String displayCard;
    private String power;
    private String memory;

    public String getCpu() {
        return cpu;
    }

    public void setCpu(String cpu) {
        this.cpu = cpu;
    }

    public String getMainBoard() {
        return mainBoard;
    }

    public void setMainBoard(String mainBoard) {
        this.mainBoard = mainBoard;
    }

    public String getHardDisk() {
        return hardDisk;
    }

    public void setHardDisk(String hardDisk) {
        this.hardDisk = hardDisk;
    }

    public String getDisplayCard() {
        return displayCard;
    }

    public void setDisplayCard(String displayCard) {
        this.displayCard = displayCard;
    }

    public String getPower() {
        return power;
    }

    public void setPower(String power) {
        this.power = power;
    }

    public String getMemory() {
        return memory;
    }

    public void setMemory(String memory) {
        this.memory = memory;
    }

    @Override
    public String toString() {
        return "Computer{" +
                "cpu='" + cpu + '\'' +
                ", mainBoard='" + mainBoard + '\'' +
                ", hardDisk='" + hardDisk + '\'' +
                ", displayCard='" + displayCard + '\'' +
                ", power='" + power + '\'' +
                ", memory='" + memory + '\'' +
                '}';
    }
}

Director类

public class DirectorBoss {
    private Builder builder;

    public void setBuilder(Builder builder) {
        this.builder = builder;
    }

    public Computer createComputer(String cpu,String mainBoard,
                                   String hardDisk,String displayCard,
                                   String power,String memory){
        this.builder.buildCPU(cpu);
        this.builder.buildMainBoard(mainBoard);
        this.builder.buildHardDisk(hardDisk);
        this.builder.buildDisplayCard(displayCard);
        this.builder.buildPower(power);
        this.builder.buildMemory(memory);
        return this.builder.createComputer();
    }

}

测试

public class Test {
    public static void main(String[] args) {
        Builder builder = new ActualBuilder();
        DirectorBoss directorBoss = new DirectorBoss();
        directorBoss.setBuilder(builder);

        Computer computer = directorBoss.createComputer("酷睿I7","华硕主板","希捷2T硬盘","英伟达显卡","长城电源","威刚内存条8G");

        System.out.println(computer);

    }
}

输出
在这里插入图片描述

对于组装电脑,是先装cpu,还是先装硬盘,只需要调整DirectorBoss类的执行顺序即可

当然,也可以用这种链式调用

public class Test {
    public static void main(String[] args) {
        Computer computer = new Computer.ComputerBuilder().buildCPU("酷睿I7").buildMainBoard("华硕主板").build();
        System.out.println(computer);
    }
}

在Computer类里面增加内部ComputerBuilder类并实现构造函数即可,这样调用顺序就可以控制在应用层

public class Computer {

    private String cpu;
    private String mainBoard;
    private String hardDisk;
    private String displayCard;
    private String power;
    private String memory;

    public Computer(ComputerBuilder computerBuilder){
        this.cpu = computerBuilder.cpu;
        this.mainBoard = computerBuilder.mainBoard;
        this.hardDisk = computerBuilder.hardDisk;
        this.displayCard = computerBuilder.displayCard;
        this.power = computerBuilder.power;
        this.memory = computerBuilder.memory;
    }

    @Override
    public String toString() {
        return "Computer{" +
                "cpu='" + cpu + '\'' +
                ", mainBoard='" + mainBoard + '\'' +
                ", hardDisk='" + hardDisk + '\'' +
                ", displayCard='" + displayCard + '\'' +
                ", power='" + power + '\'' +
                ", memory='" + memory + '\'' +
                '}';
    }

    public static class ComputerBuilder{

        private String cpu;
        private String mainBoard;
        private String hardDisk;
        private String displayCard;
        private String power;
        private String memory;

        public ComputerBuilder buildCPU(String cpu){
            this.cpu = cpu;
            return this;
        }
        public ComputerBuilder buildMainBoard(String mainBoard){
            this.mainBoard = mainBoard;
            return this;
        }
        public ComputerBuilder buildHardDisk(String hardDisk){
            this.hardDisk = hardDisk;
            return this;
        }
        public ComputerBuilder buildDisplayCard(String displayCard){
            this.displayCard = displayCard;
            return this;
        }
        public ComputerBuilder buildPower(String power){
            this.power = power;
            return this;
        }
        public ComputerBuilder buildMemory(String memory){
            this.memory = memory;
            return this;
        }
        public Computer build(){
            return new Computer(this);
        }

    }

}

输出
在这里插入图片描述

现在来看在源码中的应用:

在StringBuilder中,可以看到其也是使用了建造者模式

 @Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }

在这里插入图片描述
再看看BeanDefinitionBuilder类
在这里插入图片描述
来到setFactoryMethod方法,我们写的第二种与其类似,就是典型的建造者模式
在这里插入图片描述
MyBatis中的SqlSessionFactoryBuilder类,也是用了建造者模式,返回SqlSessionFactory对象
在这里插入图片描述
看其中一个build方法

public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }

在这里插入图片描述
在这里插入图片描述
parser.parse()调用了哪个函数,可以看到来到了XMLConfigBuilder类里面,看类名不难猜出又用了建造者模式
在这里插入图片描述
可以看到在parseConfiguration方法的参数就是一个根节点,内部就是各个组件的装配流程
至此可以知道XMLConfigBuilder创建复杂对象的Configuration,而SqlSessionFactoryBuilder只不过是对XMLConfigBuilder做了一层简单的封装,用建造者来包装一层建造者

再来看看SqlSessionManager类,可以明显看出多个newInnetstance重载函数的就调用了SqlSessionFactoryBuilder建造者来创建复杂对象

public class SqlSessionManager implements SqlSessionFactory, SqlSession {

  private final SqlSessionFactory sqlSessionFactory;
  private final SqlSession sqlSessionProxy;

  private ThreadLocal<SqlSession> localSqlSession = new ThreadLocal<SqlSession>();

  private SqlSessionManager(SqlSessionFactory sqlSessionFactory) {
    this.sqlSessionFactory = sqlSessionFactory;
    this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance(
        SqlSessionFactory.class.getClassLoader(),
        new Class[]{SqlSession.class},
        new SqlSessionInterceptor());
  }

  public static SqlSessionManager newInnetstance(Reader reader) {
    return new SqlSessionManager(new SqlSessionFactoryBuilder().build(reader, null, null));
  }

  public static SqlSessionManager newInstance(Reader reader, String environment) {
    return new SqlSessionManager(new SqlSessionFactoryBuilder().build(reader, environment, null));
  }

  public static SqlSessionManager newInstance(Reader reader, Properties properties) {
    return new SqlSessionManager(new SqlSessionFactoryBuilder().build(reader, null, properties));
  }

  public static SqlSessionManager newInstance(InputStream inputStream) {
    return new SqlSessionManager(new SqlSessionFactoryBuilder().build(inputStream, null, null));
  }

  public static SqlSessionManager newInstance(InputStream inputStream, String environment) {
    return new SqlSessionManager(new SqlSessionFactoryBuilder().build(inputStream, environment, null));
  }

  public static SqlSessionManager newInstance(InputStream inputStream, Properties properties) {
    return new SqlSessionManager(new SqlSessionFactoryBuilder().build(inputStream, null, properties));
  }

  public static SqlSessionManager newInstance(SqlSessionFactory sqlSessionFactory) {
    return new SqlSessionManager(sqlSessionFactory);
  }
  ...
}

参考:

https://zhuanlan.zhihu.com/p/58093669
http://www.imooc.com/t/2705746

posted @ 2020-05-22 22:26  八吨车  阅读(224)  评论(0编辑  收藏  举报