建造者模式
什么是建造者模式?
建造者模式(Builder Pattern)是一种创建型设计模式,它允许你分步骤构建复杂对象。就像搭积木一样,你可以一步一步地组装出最终的产品,而不需要一次性创建所有组件。
为什么使用建造者模式?
想象一下你要组装一台电脑:
- 你可以选择不同的 CPU、内存、硬盘、显卡等组件
- 每个组件都有多种选择
- 最终组装出一台完整的电脑
建造者模式就是帮你管理这种复杂对象的创建过程,让代码更清晰、更易维护。
使用场景
- 复杂对象的创建:当对象有很多可选参数时
- 对象创建过程复杂:需要分步骤构建
- 不可变对象:创建后不允许修改的对象
- 参数验证:在创建过程中进行参数检查
示例一:电脑组装
让我们用一个电脑组装的例子来说明建造者模式:
// 产品类 - 电脑
public class Computer {
private String cpu;
private String memory;
private String storage;
private String graphicsCard;
private String motherboard;
// 私有构造函数,只能通过Builder创建
private Computer() {}
// Getter方法
public String getCpu() { return cpu; }
public String getMemory() { return memory; }
public String getStorage() { return storage; }
public String getGraphicsCard() { return graphicsCard; }
public String getMotherboard() { return motherboard; }
@Override
public String toString() {
return "Computer{" +
"cpu='" + cpu + '\'' +
", memory='" + memory + '\'' +
", storage='" + storage + '\'' +
", graphicsCard='" + graphicsCard + '\'' +
", motherboard='" + motherboard + '\'' +
'}';
}
// 静态内部Builder类
public static class Builder {
private Computer computer;
public Builder() {
computer = new Computer();
}
public Builder cpu(String cpu) {
computer.cpu = cpu;
return this;
}
public Builder memory(String memory) {
computer.memory = memory;
return this;
}
public Builder storage(String storage) {
computer.storage = storage;
return this;
}
public Builder graphicsCard(String graphicsCard) {
computer.graphicsCard = graphicsCard;
return this;
}
public Builder motherboard(String motherboard) {
computer.motherboard = motherboard;
return this;
}
public Computer build() {
// 验证必要参数
if (computer.cpu == null) {
throw new IllegalArgumentException("CPU是必需的");
}
if (computer.memory == null) {
throw new IllegalArgumentException("内存是必需的");
}
return computer;
}
}
}
// 使用示例
public class ComputerBuilderExample {
public static void main(String[] args) {
// 创建游戏电脑
Computer gamingComputer = new Computer.Builder()
.cpu("Intel i7-12700K")
.memory("32GB DDR4")
.storage("1TB NVMe SSD")
.graphicsCard("RTX 4080")
.motherboard("Z690")
.build();
System.out.println("游戏电脑: " + gamingComputer);
// 创建办公电脑
Computer officeComputer = new Computer.Builder()
.cpu("Intel i5-12400")
.memory("16GB DDR4")
.storage("512GB SSD")
.motherboard("B660")
.build();
System.out.println("办公电脑: " + officeComputer);
}
}
示例二:披萨制作
再来看一个披萨制作的例子,展示如何用建造者模式制作不同口味的披萨:
// 披萨类
public class Pizza {
private String size;
private String crust;
private String sauce;
private List<String> toppings;
private boolean extraCheese;
private boolean spicy;
private Pizza() {
this.toppings = new ArrayList<>();
}
// Getter方法
public String getSize() { return size; }
public String getCrust() { return crust; }
public String getSauce() { return sauce; }
public List<String> getToppings() { return new ArrayList<>(toppings); }
public boolean isExtraCheese() { return extraCheese; }
public boolean isSpicy() { return spicy; }
@Override
public String toString() {
return "Pizza{" +
"size='" + size + '\'' +
", crust='" + crust + '\'' +
", sauce='" + sauce + '\'' +
", toppings=" + toppings +
", extraCheese=" + extraCheese +
", spicy=" + spicy +
'}';
}
// Builder类
public static class Builder {
private Pizza pizza;
public Builder() {
pizza = new Pizza();
}
public Builder size(String size) {
pizza.size = size;
return this;
}
public Builder crust(String crust) {
pizza.crust = crust;
return this;
}
public Builder sauce(String sauce) {
pizza.sauce = sauce;
return this;
}
public Builder addTopping(String topping) {
pizza.toppings.add(topping);
return this;
}
public Builder extraCheese() {
pizza.extraCheese = true;
return this;
}
public Builder spicy() {
pizza.spicy = true;
return this;
}
public Pizza build() {
// 验证必要参数
if (pizza.size == null) {
throw new IllegalArgumentException("披萨尺寸是必需的");
}
if (pizza.crust == null) {
throw new IllegalArgumentException("披萨饼底是必需的");
}
if (pizza.sauce == null) {
pizza.sauce = "番茄酱"; // 默认酱料
}
return pizza;
}
}
}
// 使用示例
public class PizzaBuilderExample {
public static void main(String[] args) {
// 制作夏威夷披萨
Pizza hawaiianPizza = new Pizza.Builder()
.size("大号")
.crust("薄底")
.sauce("番茄酱")
.addTopping("火腿")
.addTopping("菠萝")
.addTopping("青椒")
.extraCheese()
.build();
System.out.println("夏威夷披萨: " + hawaiianPizza);
// 制作辣味披萨
Pizza spicyPizza = new Pizza.Builder()
.size("中号")
.crust("厚底")
.sauce("辣酱")
.addTopping("香肠")
.addTopping("辣椒")
.addTopping("洋葱")
.addTopping("蘑菇")
.spicy()
.build();
System.out.println("辣味披萨: " + spicyPizza);
}
}
示例三:HTTP 请求构建器
最后看一个更实用的 HTTP 请求构建器示例:
// HTTP请求类
public class HttpRequest {
private String method;
private String url;
private Map<String, String> headers;
private String body;
private int timeout;
private boolean followRedirects;
private HttpRequest() {
this.headers = new HashMap<>();
this.timeout = 30000; // 默认30秒
this.followRedirects = true;
}
// Getter方法
public String getMethod() { return method; }
public String getUrl() { return url; }
public Map<String, String> getHeaders() { return new HashMap<>(headers); }
public String getBody() { return body; }
public int getTimeout() { return timeout; }
public boolean isFollowRedirects() { return followRedirects; }
@Override
public String toString() {
return "HttpRequest{" +
"method='" + method + '\'' +
", url='" + url + '\'' +
", headers=" + headers +
", body='" + body + '\'' +
", timeout=" + timeout +
", followRedirects=" + followRedirects +
'}';
}
// Builder类
public static class Builder {
private HttpRequest request;
public Builder() {
request = new HttpRequest();
}
public Builder method(String method) {
request.method = method.toUpperCase();
return this;
}
public Builder url(String url) {
request.url = url;
return this;
}
public Builder header(String key, String value) {
request.headers.put(key, value);
return this;
}
public Builder body(String body) {
request.body = body;
return this;
}
public Builder timeout(int timeout) {
request.timeout = timeout;
return this;
}
public Builder followRedirects(boolean followRedirects) {
request.followRedirects = followRedirects;
return this;
}
public HttpRequest build() {
// 验证必要参数
if (request.method == null) {
throw new IllegalArgumentException("HTTP方法不能为空");
}
if (request.url == null) {
throw new IllegalArgumentException("URL不能为空");
}
// 设置默认Content-Type
if (request.body != null && !request.headers.containsKey("Content-Type")) {
request.headers.put("Content-Type", "application/json");
}
return request;
}
}
}
// 使用示例
public class HttpRequestBuilderExample {
public static void main(String[] args) {
// 创建GET请求
HttpRequest getRequest = new HttpRequest.Builder()
.method("GET")
.url("https://api.example.com/users")
.header("Authorization", "Bearer token123")
.header("Accept", "application/json")
.timeout(5000)
.build();
System.out.println("GET请求: " + getRequest);
// 创建POST请求
HttpRequest postRequest = new HttpRequest.Builder()
.method("POST")
.url("https://api.example.com/users")
.header("Authorization", "Bearer token123")
.header("Accept", "application/json")
.body("{\"name\":\"张三\",\"age\":25}")
.timeout(10000)
.followRedirects(false)
.build();
System.out.println("POST请求: " + postRequest);
}
}
优缺点
优点
- ✅ 可以精确控制对象的创建过程
- ✅ 代码更易读和维护
- ✅ 可以创建不可变对象
- ✅ 支持链式调用
- ✅ 参数验证更容易
缺点
- ❌ 代码量增加
- ❌ 对于简单对象可能过度设计
- ❌ 需要创建多个类
总结
建造者模式的核心思想是:
- 分离关注点:将对象的创建和表示分离
- 分步构建:可以逐步设置对象的属性
- 链式调用:提供流畅的 API
- 参数验证:在构建过程中进行验证
- 不可变性:创建不可变对象
这种模式特别适合创建复杂对象,让代码更加清晰和易于维护。就像搭积木一样,你可以一步一步地构建出你想要的对象!
