建造者模式 (Builder Pattern)
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
模式定义
建造者模式是一种创建型设计模式,它能将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。建造者模式关注如何分步创建复杂对象。
适用场景
- 需要生成的对象具有复杂的内部结构
- 需要生成的对象的属性相互依赖,需要指定其生成顺序
- 隔离复杂对象的创建和使用,使得相同的创建过程可以创建不同的产品
- 对象的创建过程独立于创建该对象的类
结构图
graph TD
A[Director] --> B{construct}
B --> C[Builder]
C --> D{buildPartA}
C --> E{buildPartB}
C --> F{buildPartC}
G[ConcreteBuilder] --> H{buildPartA}
G --> I{buildPartB}
G --> J{buildPartC}
G --> K[Product]
实现示例
Java 实现
// 产品类
public class Product {
private String partA;
private String partB;
private String partC;
public void setPartA(String partA) {
this.partA = partA;
}
public void setPartB(String partB) {
this.partB = partB;
}
public void setPartC(String partC) {
this.partC = partC;
}
public void show() {
System.out.println("Product Parts: " + partA + ", " + partB + ", " + partC);
}
}
// 抽象建造者
public abstract class Builder {
protected Product product = new Product();
public abstract void buildPartA();
public abstract void buildPartB();
public abstract void buildPartC();
public Product getResult() {
return product;
}
}
// 具体建造者
public class ConcreteBuilder extends Builder {
@Override
public void buildPartA() {
product.setPartA("建造 PartA");
}
@Override
public void buildPartB() {
product.setPartB("建造 PartB");
}
@Override
public void buildPartC() {
product.setPartC("建造 PartC");
}
}
// 指挥者
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public Product construct() {
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
return builder.getResult();
}
}
经典案例
1. StringBuilder类
Java标准库中的StringBuilder就是建造者模式的应用:
// StringBuilder是建造者模式的典型应用
public class StringBuilderExample {
public static void main(String[] args) {
// 使用StringBuilder逐步构建字符串
StringBuilder builder = new StringBuilder();
builder.append("Hello");
builder.append(" ");
builder.append("World");
builder.append("!");
// 最终获取结果
String result = builder.toString();
System.out.println(result); // 输出: Hello World!
// StringBuilder内部逐步构建字符串对象
// 每次append操作都是在构建最终的字符串表示
}
}
// StringBuilder的简化实现示例
public class SimpleStringBuilder {
private char[] value;
private int count;
public SimpleStringBuilder() {
this(16);
}
public SimpleStringBuilder(int capacity) {
value = new char[capacity];
}
// 建造者方法 - 逐步构建字符串
public SimpleStringBuilder append(String str) {
if (str == null) str = "null";
int len = str.length();
ensureCapacity(count + len);
str.getChars(0, len, value, count);
count += len;
return this;
}
// 建造者方法
public SimpleStringBuilder append(int i) {
return append(String.valueOf(i));
}
// 建造者方法
public SimpleStringBuilder append(char c) {
ensureCapacity(count + 1);
value[count++] = c;
return this;
}
// 获取最终构建的产品
public String toString() {
return new String(value, 0, count);
}
private void ensureCapacity(int minimumCapacity) {
if (minimumCapacity - value.length > 0) {
expandCapacity(minimumCapacity);
}
}
private void expandCapacity(int minimumCapacity) {
int newCapacity = value.length * 2 + 2;
if (newCapacity - minimumCapacity < 0)
newCapacity = minimumCapacity;
value = Arrays.copyOf(value, newCapacity);
}
}
2. Spring框架中的BeanDefinitionBuilder
Spring框架中使用建造者模式来构建Bean定义:
// Spring中的BeanDefinitionBuilder使用了建造者模式
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
public class SpringBeanBuilderExample {
public static void main(String[] args) {
// 使用BeanDefinitionBuilder逐步构建Bean定义
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.rootBeanDefinition(MyService.class)
.addPropertyValue("name", "testService")
.addPropertyValue("timeout", 5000)
.setScope("prototype")
.setLazyInit(false);
// 获取最终的Bean定义
RootBeanDefinition beanDefinition =
(RootBeanDefinition) builder.getBeanDefinition();
// 注册到Bean工厂
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
factory.registerBeanDefinition("myService", beanDefinition);
}
}
// 自定义服务类
class MyService {
private String name;
private int timeout;
// getter和setter方法
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getTimeout() { return timeout; }
public void setTimeout(int timeout) { this.timeout = timeout; }
}
3. HTTP请求构建
在实际项目中,建造者模式常用于构建复杂的HTTP请求:
// HTTP请求建造者模式实现
public class HttpRequest {
private String url;
private String method;
private Map headers;
private String body;
private int timeout;
private HttpRequest(Builder builder) {
this.url = builder.url;
this.method = builder.method;
this.headers = builder.headers;
this.body = builder.body;
this.timeout = builder.timeout;
}
// getter方法
public String getUrl() { return url; }
public String getMethod() { return method; }
public Map getHeaders() { return headers; }
public String getBody() { return body; }
public int getTimeout() { return timeout; }
// 静态内部建造者类
public static class Builder {
private String url;
private String method = "GET";
private Map headers = new HashMap<>();
private String body;
private int timeout = 5000;
public Builder(String url) {
this.url = url;
}
public Builder method(String method) {
this.method = method;
return this;
}
public Builder addHeader(String key, String value) {
this.headers.put(key, value);
return this;
}
public Builder body(String body) {
this.body = body;
return this;
}
public Builder timeout(int timeout) {
this.timeout = timeout;
return this;
}
public HttpRequest build() {
// 可以在这里添加验证逻辑
if (url == null || url.isEmpty()) {
throw new IllegalArgumentException("URL不能为空");
}
return new HttpRequest(this);
}
}
@Override
public String toString() {
return "HttpRequest{" +
"url='" + url + '\'' +
", method='" + method + '\'' +
", headers=" + headers +
", body='" + body + '\'' +
", timeout=" + timeout +
'}';
}
}
// 使用示例
public class HttpRequestBuilderExample {
public static void main(String[] args) {
// 使用建造者模式构建HTTP请求
HttpRequest request = new HttpRequest.Builder("https://api.example.com/users")
.method("POST")
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", "Bearer token123")
.body("{\"name\":\"张三\", \"age\":30}")
.timeout(10000)
.build();
System.out.println(request);
// 发送请求的逻辑...
// sendRequest(request);
}
// 模拟发送请求的方法
private static void sendRequest(HttpRequest request) {
System.out.println("发送请求到: " + request.getUrl());
System.out.println("方法: " + request.getMethod());
System.out.println("头部: " + request.getHeaders());
System.out.println("内容: " + request.getBody());
System.out.println("超时: " + request.getTimeout() + "ms");
}
}
优缺点
优点
- 建造者独立,易扩展
- 便于控制细节风险
- 产品的创建过程可以被精确控制
缺点
- 产品必须有共同点,范围有限制
- 如内部变化复杂,会有很多的建造类