Zer0e's Blog

设计模式之构建模式

字数统计: 1k阅读时长: 3 min
2020/09/14 Share

前言

构建模式又称建造模式,建造者模式等等。
本篇来简单谈谈这种设计模式。

正文

概念

构建模式(Builder Pattern),由于存在多种叫法,为了统一名称,统一写作Builder模式。它属于创建型模式,是使用一个个对象构建复杂对象的设计模式。
它的意图在于拆分复杂对象,使得可以由子对象生成,子对象相对稳定,通过组合子对象来构造复杂对象。
那使用的场景通常是对象的内部结构较为复杂或者内部属性相互依赖。
那Java中常见的就是各种Builder,例如StringBuilder。
那项目中何时使用这种设计模式呢?通常来说,当类的构造函数非常多时(大于4个)可以改用Builder模式来创建对象。

实现

先来讲讲Builder模式中的几个角色:

  • Builder角色:一个接口,规范产品对象中各个子对象的构建。
  • ConcreteBuilder:具体的实现类,提供产品的实例。
  • Director:负责调用具体的ConcreteBuilder来创建对象。
  • Product:即我们需要构建的复杂对象。

我们就用这几个角色来写写基础的Builder模式。
首先我们定义我们的Product对象中,有两个string担任它的子对象。那我们可以写出代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Product {
private String id;
private String name;

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

首先这个类并没有构造器,而是采用javabean的方式来设置对象,这有利于我们使用builder来创建这个对象。
接着我们写抽象的Builder接口

1
2
3
4
5
public interface Builder {
public void buildId();
public void buildName();
public Product getProduct();
}

这个接口中有两个方法用来创建product对象中的子对象。而第三个方法则是来获取一个创建完成的product对象。
接着是ConcreteBuilder

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class ConcreteBuilder implements Builder{
private Product product = new Product();
@Override
public void buildId() {
product.setId("01");
}

@Override
public void buildName() {
product.setName("产品1");
}

@Override
public Product getProduct() {
return product;
}
}

接着是导演类,用来引导ConcreteBuilder创建对象。

1
2
3
4
5
6
7
8
9
10
11
public class Director {
private Builder builder;

public Director(Builder builder) {
this.builder = builder;
}
public void construct(){
builder.buildId();
builder.buildName();
}
}

我们通过把builder传递给导演类,然后调用导演类的construct方法,就可以创建一个product对象到builder对象中,获取就可以得到这个product对象。

1
2
3
4
5
6
7
8
9
10
11
public class Client {
public static void main(String[] args) {
Builder builder = new ConcreteBuilder();
Director director = new Director(builder);
director.construct();
Product product = builder.getProduct();

System.out.println(product.getId());
System.out.println(product.getName());
}
}

如此我们便简单实现了Builder模式。
那实际场景中哪里使用到了Builder模式呢?
MyBatis中就大量使用了这个模式。原生的mybatis(不整合spring)在SqlSessionFactory中使用了XMLConfigBuilder,得益于builder模式,mybatis隐藏了解析XML文件的细节,我们只需要少量的基本参数(比如地址,账号密码等),就可以使用。其他参数根据用户是否提供,如果没有就使用默认参数。因此mybatis使用成本大大降低。

tips

所以当我们在编写复杂类,或者是一个大型框架时,可以采用Builder模式,将大量参数通过这个模式来创建对象,而不是使用构造函数来创建。

优缺点

那Builder模式的优点在于可以精确控制产品的创建,开发者可以根据需要创建出想要的对象。其次,客户端可以不知道产品内部实现细节,结果与过程解耦。最后添加新的Builder无需修改原有代码,Director是针对Builder进行编程的,所以方便系统扩展,符合开闭原则。
那缺点就是产品之间需要有共同点,有所限制。其次就是如果内部复杂,会导致Builder过多,系统臃肿。

CATALOG
  1. 1. 前言
  2. 2. 正文
    1. 2.1. 概念
    2. 2.2. 实现
    3. 2.3. tips
    4. 2.4. 优缺点