23种设计模式23种设计模式
首页
介绍
  • 单例模式
  • 工厂方法模式
  • 抽象工厂模式
  • 建造者模式
  • 原型模式
  • 适配器模式
  • 桥接模式
  • 组合模式
  • 装饰器模式
  • 外观模式
  • 享元模式
  • 代理模式
  • 责任链模式
  • 命令模式
  • 解释器模式
  • 迭代器模式
  • 中介者模式
  • 备忘录模式
  • 观察者模式
  • 状态模式
  • 策略模式
  • 模板方法模式
  • 访问者模式
🚀 编程指南
首页
介绍
  • 单例模式
  • 工厂方法模式
  • 抽象工厂模式
  • 建造者模式
  • 原型模式
  • 适配器模式
  • 桥接模式
  • 组合模式
  • 装饰器模式
  • 外观模式
  • 享元模式
  • 代理模式
  • 责任链模式
  • 命令模式
  • 解释器模式
  • 迭代器模式
  • 中介者模式
  • 备忘录模式
  • 观察者模式
  • 状态模式
  • 策略模式
  • 模板方法模式
  • 访问者模式
🚀 编程指南
  • 创建型模式

    • 单例模式 (Singleton)
    • 工厂方法模式 (Factory Method)
    • 抽象工厂模式 (Abstract Factory)
    • 建造者模式 (Builder)
    • 原型模式 (Prototype)

建造者模式 (Builder)

📖 通俗理解

想象你去电脑城组装电脑:

  • 你告诉店员:我要 i7 CPU、32G 内存、RTX 4090 显卡...
  • 店员一步步帮你装好:装 CPU → 装内存 → 装显卡 → 装硬盘...
  • 最后给你一台完整的电脑

建造者模式就是:将复杂对象的构建过程分解成多个简单步骤,一步步构建。

🎯 解决什么问题?

问题场景:创建一个复杂对象,构造函数有很多参数:

// 构造函数有10个参数,谁能记得住顺序?
Computer computer = new Computer("Intel i7", "NVIDIA RTX4090", 
    "32GB", "1TB SSD", "华硕", "750W", "Windows 11", 
    true, true, "黑色");

问题:

  • 参数太多,容易传错
  • 有些参数可选,有些必填,逻辑复杂
  • 代码可读性差

建造者模式的解决方案:

// 链式调用,清晰易读
Computer computer = new Computer.Builder()
    .cpu("Intel i7")
    .gpu("NVIDIA RTX4090")
    .memory("32GB")
    .storage("1TB SSD")
    .build();

🌰 生活中的例子

  • 组装电脑:按步骤安装各个配件
  • 建造房子:打地基 → 建框架 → 装修 → 交付
  • 做汉堡:烤面包 → 放肉饼 → 加蔬菜 → 挤酱料
  • 配置游戏角色:选职业 → 选技能 → 选装备 → 起名字

💻 Java 代码实现

方式一:经典建造者模式

第一步:定义产品类

/**
 * 产品类:电脑
 */
public class Computer {
    // 必选配置
    private String cpu;
    private String memory;
    
    // 可选配置
    private String gpu;
    private String storage;
    private String monitor;
    private String keyboard;
    private String mouse;
    
    // 私有构造,只能通过 Builder 创建
    private Computer(Builder builder) {
        this.cpu = builder.cpu;
        this.memory = builder.memory;
        this.gpu = builder.gpu;
        this.storage = builder.storage;
        this.monitor = builder.monitor;
        this.keyboard = builder.keyboard;
        this.mouse = builder.mouse;
    }
    
    @Override
    public String toString() {
        return "Computer{" +
            "cpu='" + cpu + '\'' +
            ", memory='" + memory + '\'' +
            ", gpu='" + gpu + '\'' +
            ", storage='" + storage + '\'' +
            ", monitor='" + monitor + '\'' +
            ", keyboard='" + keyboard + '\'' +
            ", mouse='" + mouse + '\'' +
            '}';
    }
    
    // ========== 静态内部类 Builder ==========
    public static class Builder {
        // 必选参数
        private String cpu;
        private String memory;
        
        // 可选参数,设置默认值
        private String gpu = "集成显卡";
        private String storage = "256GB SSD";
        private String monitor = "无";
        private String keyboard = "无";
        private String mouse = "无";
        
        // 必选参数通过构造方法传入
        public Builder(String cpu, String memory) {
            this.cpu = cpu;
            this.memory = memory;
        }
        
        // 可选参数通过 setter 方法链式调用
        public Builder gpu(String gpu) {
            this.gpu = gpu;
            return this;
        }
        
        public Builder storage(String storage) {
            this.storage = storage;
            return this;
        }
        
        public Builder monitor(String monitor) {
            this.monitor = monitor;
            return this;
        }
        
        public Builder keyboard(String keyboard) {
            this.keyboard = keyboard;
            return this;
        }
        
        public Builder mouse(String mouse) {
            this.mouse = mouse;
            return this;
        }
        
        // 构建最终对象
        public Computer build() {
            return new Computer(this);
        }
    }
}

第二步:使用建造者

public class Client {
    public static void main(String[] args) {
        // 基础配置电脑
        Computer basicPC = new Computer.Builder("Intel i3", "8GB")
            .build();
        System.out.println("基础配置: " + basicPC);
        
        // 游戏电脑
        Computer gamingPC = new Computer.Builder("Intel i7", "32GB")
            .gpu("NVIDIA RTX 4090")
            .storage("2TB SSD")
            .monitor("27寸 4K 显示器")
            .keyboard("机械键盘")
            .mouse("游戏鼠标")
            .build();
        System.out.println("游戏配置: " + gamingPC);
        
        // 办公电脑
        Computer officePC = new Computer.Builder("Intel i5", "16GB")
            .storage("512GB SSD")
            .monitor("24寸显示器")
            .build();
        System.out.println("办公配置: " + officePC);
    }
}

输出结果:

基础配置: Computer{cpu='Intel i3', memory='8GB', gpu='集成显卡', storage='256GB SSD', monitor='无', keyboard='无', mouse='无'}
游戏配置: Computer{cpu='Intel i7', memory='32GB', gpu='NVIDIA RTX 4090', storage='2TB SSD', monitor='27寸 4K 显示器', keyboard='机械键盘', mouse='游戏鼠标'}
办公配置: Computer{cpu='Intel i5', memory='16GB', gpu='集成显卡', storage='512GB SSD', monitor='24寸显示器', keyboard='无', mouse='无'}

方式二:带 Director 的建造者模式

当有固定的构建流程时,可以使用 Director(指挥者)来封装构建步骤。

/**
 * 产品:汉堡
 */
public class Burger {
    private String bread;
    private String meat;
    private String vegetable;
    private String sauce;
    
    // getter 和 setter...
    
    @Override
    public String toString() {
        return String.format("汉堡[%s + %s + %s + %s]", 
            bread, meat, vegetable, sauce);
    }
}

/**
 * 抽象建造者
 */
public abstract class BurgerBuilder {
    protected Burger burger = new Burger();
    
    public abstract void buildBread();
    public abstract void buildMeat();
    public abstract void buildVegetable();
    public abstract void buildSauce();
    
    public Burger getResult() {
        return burger;
    }
}

/**
 * 具体建造者:鸡肉汉堡
 */
public class ChickenBurgerBuilder extends BurgerBuilder {
    @Override
    public void buildBread() {
        burger.setBread("全麦面包");
    }
    
    @Override
    public void buildMeat() {
        burger.setMeat("鸡肉饼");
    }
    
    @Override
    public void buildVegetable() {
        burger.setVegetable("生菜+番茄");
    }
    
    @Override
    public void buildSauce() {
        burger.setSauce("蜂蜜芥末酱");
    }
}

/**
 * 具体建造者:牛肉汉堡
 */
public class BeefBurgerBuilder extends BurgerBuilder {
    @Override
    public void buildBread() {
        burger.setBread("芝麻面包");
    }
    
    @Override
    public void buildMeat() {
        burger.setMeat("双层牛肉饼");
    }
    
    @Override
    public void buildVegetable() {
        burger.setVegetable("洋葱+酸黄瓜");
    }
    
    @Override
    public void buildSauce() {
        burger.setSauce("番茄酱+芝士");
    }
}

/**
 * 指挥者:定义构建步骤
 */
public class BurgerDirector {
    private BurgerBuilder builder;
    
    public BurgerDirector(BurgerBuilder builder) {
        this.builder = builder;
    }
    
    // 指挥构建过程
    public Burger construct() {
        builder.buildBread();
        builder.buildMeat();
        builder.buildVegetable();
        builder.buildSauce();
        return builder.getResult();
    }
}

使用方式:

public class Client {
    public static void main(String[] args) {
        // 做一个鸡肉汉堡
        BurgerDirector director1 = new BurgerDirector(new ChickenBurgerBuilder());
        Burger chickenBurger = director1.construct();
        System.out.println("鸡肉汉堡: " + chickenBurger);
        
        // 做一个牛肉汉堡
        BurgerDirector director2 = new BurgerDirector(new BeefBurgerBuilder());
        Burger beefBurger = director2.construct();
        System.out.println("牛肉汉堡: " + beefBurger);
    }
}

🔥 实战案例:HTTP 请求构建器

/**
 * HTTP 请求对象
 */
public class HttpRequest {
    private final String url;
    private final String method;
    private final Map<String, String> headers;
    private final Map<String, String> params;
    private final String body;
    private final int timeout;
    
    private HttpRequest(Builder builder) {
        this.url = builder.url;
        this.method = builder.method;
        this.headers = builder.headers;
        this.params = builder.params;
        this.body = builder.body;
        this.timeout = builder.timeout;
    }
    
    public void send() {
        System.out.println("发送 HTTP 请求:");
        System.out.println("  URL: " + url);
        System.out.println("  Method: " + method);
        System.out.println("  Headers: " + headers);
        System.out.println("  Params: " + params);
        System.out.println("  Body: " + body);
        System.out.println("  Timeout: " + timeout + "ms");
    }
    
    public static class Builder {
        private String url;
        private String method = "GET";
        private Map<String, String> headers = new HashMap<>();
        private Map<String, String> params = new HashMap<>();
        private String body;
        private int timeout = 30000;
        
        public Builder(String url) {
            this.url = url;
        }
        
        public Builder method(String method) {
            this.method = method;
            return this;
        }
        
        public Builder get() {
            this.method = "GET";
            return this;
        }
        
        public Builder post() {
            this.method = "POST";
            return this;
        }
        
        public Builder header(String key, String value) {
            this.headers.put(key, value);
            return this;
        }
        
        public Builder param(String key, String value) {
            this.params.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 IllegalStateException("URL 不能为空");
            }
            return new HttpRequest(this);
        }
    }
}

使用方式:

public class Client {
    public static void main(String[] args) {
        // GET 请求
        HttpRequest getRequest = new HttpRequest.Builder("https://api.example.com/users")
            .get()
            .header("Authorization", "Bearer token123")
            .param("page", "1")
            .param("size", "10")
            .timeout(5000)
            .build();
        getRequest.send();
        
        System.out.println("-------------------");
        
        // POST 请求
        HttpRequest postRequest = new HttpRequest.Builder("https://api.example.com/users")
            .post()
            .header("Content-Type", "application/json")
            .body("{\"name\": \"张三\", \"age\": 25}")
            .build();
        postRequest.send();
    }
}

✅ 适用场景

  1. 对象构造复杂:有很多配置参数
  2. 需要创建不同表示:同样的构建过程可以创建不同的对象
  3. 需要参数校验:在 build() 方法中统一校验

⚠️ 优缺点

优点:

  • 链式调用,代码优雅
  • 参数可选,灵活配置
  • 可以在 build() 中做统一校验
  • 创建的对象不可变(线程安全)

缺点:

  • 代码量增加(需要额外的 Builder 类)
  • 不适合简单对象

📚 框架中的应用

  • StringBuilder:new StringBuilder().append("a").append("b").toString()
  • Lombok @Builder:自动生成 Builder 代码
  • OkHttp:new Request.Builder().url(...).build()
  • Guava:ImmutableList.builder().add(...).build()

小结

建造者模式的核心:把复杂对象的构建过程拆分成多个步骤,通过链式调用一步步构建。

简单记忆:像搭积木一样,一块一块往上堆。

👉 下一篇:原型模式

Prev
抽象工厂模式 (Abstract Factory)
Next
原型模式 (Prototype)