创建型模式:建造者模式

什么是建造者模式

建造者模式(Builder Pattern)是一种创建型设计模式,它将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。简单来说,建造者模式允许您一步一步创建复杂对象,而不是一次性传入所有参数。

建造者模式特别适合那些需要多个步骤构建、有多个可选参数或者构建过程中需要遵循特定顺序的对象创建场景。

为什么需要建造者模式

假设我们有一个具有十多个属性的Computer类,其中一些属性是必需的,而其他属性是可选的。使用传统的构造函数或JavaBean模式创建对象会带来以下问题:

  1. 伸缩构造函数问题:需要编写多个构造函数来处理不同的参数组合
  2. 可读性差:当参数较多时,构造函数调用难以理解
  3. 状态不一致:使用setter方法时,对象可能处于不完整状态
  4. 线程安全问题:构建过程中对象状态可能发生变化

建造者模式优雅地解决了这些问题。

建造者模式的核心实现

java 复制代码
// 产品类
public class House {
    // 必要参数
    private final String foundation;
    private final String structure;
    private final String roof;
    
    // 可选参数
    private final String interior;
    private final String exterior;
    private final boolean hasGarage;
    private final boolean hasSwimmingPool;
    private final boolean hasGarden;
    
    // 私有构造函数,只能通过Builder访问
    private House(Builder builder) {
        this.foundation = builder.foundation;
        this.structure = builder.structure;
        this.roof = builder.roof;
        this.interior = builder.interior;
        this.exterior = builder.exterior;
        this.hasGarage = builder.hasGarage;
        this.hasSwimmingPool = builder.hasSwimmingPool;
        this.hasGarden = builder.hasGarden;
    }
    
    // Getters
    public String getFoundation() { return foundation; }
    public String getStructure() { return structure; }
    public String getRoof() { return roof; }
    public String getInterior() { return interior; }
    public String getExterior() { return exterior; }
    public boolean hasGarage() { return hasGarage; }
    public boolean hasSwimmingPool() { return hasSwimmingPool; }
    public boolean hasGarden() { return hasGarden; }
    
    @Override
    public String toString() {
        return "House with " + foundation + " foundation, " + structure + 
               " structure, " + roof + " roof, " + interior + " interior, " +
               exterior + " exterior. " +
               (hasGarage ? "Has garage. " : "") +
               (hasSwimmingPool ? "Has swimming pool. " : "") +
               (hasGarden ? "Has garden." : "");
    }
    
    // 静态内部Builder类
    public static class Builder {
        // 必要参数
        private final String foundation;
        private final String structure;
        private final String roof;
        
        // 可选参数 - 设置默认值
        private String interior = "普通装修";
        private String exterior = "标准外墙";
        private boolean hasGarage = false;
        private boolean hasSwimmingPool = false;
        private boolean hasGarden = false;
        
        // 必要参数通过构造器强制传入
        public Builder(String foundation, String structure, String roof) {
            this.foundation = foundation;
            this.structure = structure;
            this.roof = roof;
        }
        
        // 可选参数通过具有链式调用的setter方法设置
        public Builder interior(String interior) {
            this.interior = interior;
            return this;
        }
        
        public Builder exterior(String exterior) {
            this.exterior = exterior;
            return this;
        }
        
        public Builder garage(boolean hasGarage) {
            this.hasGarage = hasGarage;
            return this;
        }
        
        public Builder swimmingPool(boolean hasSwimmingPool) {
            this.hasSwimmingPool = hasSwimmingPool;
            return this;
        }
        
        public Builder garden(boolean hasGarden) {
            this.hasGarden = hasGarden;
            return this;
        }
        
        // build方法创建最终对象
        public House build() {
            // 可以在这里添加构建验证逻辑
            return new House(this);
        }
    }
}

建造者模式的关键点

  1. 产品类:复杂对象,通常是不可变的
  2. Builder类:负责定义产品创建步骤的接口
  3. 链式调用:Builder方法返回Builder自身,支持流式API
  4. 最终构建方法 :完成产品创建的方法(如build()
  5. 参数分离:将必选参数和可选参数明确区分

使用建造者模式

java 复制代码
public class BuilderPatternDemo {
    public static void main(String[] args) {
        // 使用Builder创建对象
        House simpleHouse = new House.Builder(
                "混凝土基础", 
                "砖墙结构", 
                "平顶屋顶")
                .build();
        
        System.out.println("简易房屋:");
        System.out.println(simpleHouse);
        
        // 使用Builder创建更复杂的对象,设置可选参数
        House luxuryHouse = new House.Builder(
                "深层钢筋混凝土基础", 
                "钢筋混凝土框架", 
                "坡顶屋顶")
                .interior("豪华装修")
                .exterior("大理石外墙")
                .garage(true)
                .swimmingPool(true)
                .garden(true)
                .build();
        
        System.out.println("\n豪华房屋:");
        System.out.println(luxuryHouse);
    }
}

运行结果

vbnet 复制代码
简易房屋:
House with 混凝土基础 foundation, 砖墙结构 structure, 平顶屋顶 roof, 普通装修 interior, 标准外墙 exterior. 

豪华房屋:
House with 深层钢筋混凝土基础 foundation, 钢筋混凝土框架 structure, 坡顶屋顶 roof, 豪华装修 interior, 大理石外墙 exterior. Has garage. Has swimming pool. Has garden.

建造者模式的高级版本:带Director的建造者模式

在某些情况下,我们可能需要一个额外的Director类来封装构建过程,特别是当构建过程复杂或需要被重用时。

java 复制代码
// 抽象Builder接口
public interface HouseBuilder {
    void buildFoundation();
    void buildStructure();
    void buildRoof();
    void buildInterior();
    void buildExterior();
    void buildGarage();
    void buildSwimmingPool();
    void buildGarden();
    House getResult();
}

// 具体Builder实现
public class StandardHouseBuilder implements HouseBuilder {
    private String foundation;
    private String structure;
    private String roof;
    private String interior;
    private String exterior;
    private boolean hasGarage;
    private boolean hasSwimmingPool;
    private boolean hasGarden;
    
    @Override
    public void buildFoundation() {
        this.foundation = "标准混凝土基础";
    }
    
    @Override
    public void buildStructure() {
        this.structure = "砖混结构";
    }
    
    @Override
    public void buildRoof() {
        this.roof = "普通瓦片屋顶";
    }
    
    @Override
    public void buildInterior() {
        this.interior = "基础装修";
    }
    
    @Override
    public void buildExterior() {
        this.exterior = "普通外墙";
    }
    
    @Override
    public void buildGarage() {
        this.hasGarage = false;
    }
    
    @Override
    public void buildSwimmingPool() {
        this.hasSwimmingPool = false;
    }
    
    @Override
    public void buildGarden() {
        this.hasGarden = false;
    }
    
    @Override
    public House getResult() {
        return new House(foundation, structure, roof, 
                        interior, exterior, hasGarage, 
                        hasSwimmingPool, hasGarden);
    }
}

// 另一个具体Builder实现
public class LuxuryHouseBuilder implements HouseBuilder {
    private String foundation;
    private String structure;
    private String roof;
    private String interior;
    private String exterior;
    private boolean hasGarage;
    private boolean hasSwimmingPool;
    private boolean hasGarden;
    
    @Override
    public void buildFoundation() {
        this.foundation = "深层钢筋混凝土基础";
    }
    
    // 其他方法实现...
    
    @Override
    public House getResult() {
        return new House(foundation, structure, roof, 
                        interior, exterior, hasGarage, 
                        hasSwimmingPool, hasGarden);
    }
}

// Director类
public class HouseDirector {
    private HouseBuilder builder;
    
    public HouseDirector(HouseBuilder builder) {
        this.builder = builder;
    }
    
    // 更换Builder
    public void changeBuilder(HouseBuilder builder) {
        this.builder = builder;
    }
    
    // 构建最小可居住房屋
    public void constructMinimalHouse() {
        builder.buildFoundation();
        builder.buildStructure();
        builder.buildRoof();
        builder.buildInterior();
        builder.buildExterior();
    }
    
    // 构建完整功能房屋
    public void constructFullFeaturedHouse() {
        builder.buildFoundation();
        builder.buildStructure();
        builder.buildRoof();
        builder.buildInterior();
        builder.buildExterior();
        builder.buildGarage();
        builder.buildSwimmingPool();
        builder.buildGarden();
    }
}

实际应用示例:流畅的API构建器

下面通过一个SQL查询构建器的例子来展示建造者模式在实际API设计中的应用:

java 复制代码
// SQL查询构建器
public class SQLQueryBuilder {
    private String table;
    private List<String> columns = new ArrayList<>();
    private List<String> conditions = new ArrayList<>();
    private List<String> orderBy = new ArrayList<>();
    private Integer limit;
    private Integer offset;
    
    public SQLQueryBuilder from(String table) {
        this.table = table;
        return this;
    }
    
    public SQLQueryBuilder select(String... columns) {
        if (columns.length == 0) {
            this.columns.add("*");
        } else {
            this.columns.addAll(Arrays.asList(columns));
        }
        return this;
    }
    
    public SQLQueryBuilder where(String condition) {
        this.conditions.add(condition);
        return this;
    }
    
    public SQLQueryBuilder orderBy(String column, boolean ascending) {
        this.orderBy.add(column + (ascending ? " ASC" : " DESC"));
        return this;
    }
    
    public SQLQueryBuilder limit(int limit) {
        this.limit = limit;
        return this;
    }
    
    public SQLQueryBuilder offset(int offset) {
        this.offset = offset;
        return this;
    }
    
    public String build() {
        // 验证必要参数
        if (table == null) {
            throw new IllegalStateException("表名未指定");
        }
        
        StringBuilder query = new StringBuilder();
        query.append("SELECT ");
        
        // 添加列
        if (columns.isEmpty()) {
            query.append("*");
        } else {
            query.append(String.join(", ", columns));
        }
        
        // 添加表
        query.append(" FROM ").append(table);
        
        // 添加条件
        if (!conditions.isEmpty()) {
            query.append(" WHERE ");
            query.append(String.join(" AND ", conditions));
        }
        
        // 添加排序
        if (!orderBy.isEmpty()) {
            query.append(" ORDER BY ");
            query.append(String.join(", ", orderBy));
        }
        
        // 添加限制
        if (limit != null) {
            query.append(" LIMIT ").append(limit);
        }
        
        // 添加偏移
        if (offset != null) {
            query.append(" OFFSET ").append(offset);
        }
        
        return query.toString();
    }
}

SQL构建器的使用示例

java 复制代码
public class SQLBuilderDemo {
    public static void main(String[] args) {
        // 创建简单查询
        String simpleQuery = new SQLQueryBuilder()
            .from("users")
            .select("id", "name", "email")
            .build();
        
        System.out.println("简单查询:");
        System.out.println(simpleQuery);
        
        // 创建复杂查询
        String complexQuery = new SQLQueryBuilder()
            .select("u.id", "u.name", "COUNT(o.id) as order_count")
            .from("users u LEFT JOIN orders o ON u.id = o.user_id")
            .where("u.status = 'active'")
            .where("o.create_time > '2023-01-01'")
            .orderBy("order_count", false)
            .limit(10)
            .offset(20)
            .build();
        
        System.out.println("\n复杂查询:");
        System.out.println(complexQuery);
    }
}

建造者模式的常见应用场景

  1. 文档生成器:构建HTML、PDF、Word文档
  2. 复杂对象构建:具有多个配置选项的对象
  3. 不可变对象创建:需要一次性设置所有属性的对象
  4. 流畅的API设计:提供链式调用的接口
  5. 配置构建:应用程序配置、网络请求配置等
  6. 测试数据构建:创建测试用例数据
  7. 复杂GUI创建:组装UI组件和布局

真实世界中的建造者模式应用

  1. Java中的StringBuilder/StringBuffer:字符串构建
  2. Lombok的@Builder注解:自动生成Builder代码
  3. Spring框架的UriComponentsBuilder:构建URI
  4. Apache Camel的RouteBuilder:构建路由规则
  5. Retrofit的RequestBuilder:构建HTTP请求
  6. OkHttp的Request.Builder:构建HTTP请求

建造者模式的优点

  1. 参数控制:分离必选参数和可选参数
  2. 构建过程封装:隐藏复杂构建过程的细节
  3. 可读性:创建对象的代码更具可读性
  4. 灵活性:同一构建过程可创建不同表示
  5. 不变性:可以创建不可变对象
  6. 参数验证:可在构建时检查参数有效性

建造者模式的缺点

  1. 代码量增加:需要创建额外的Builder类
  2. 复杂度:对于简单对象,可能过于复杂
  3. 性能开销:相比直接构造,略有性能损失
  4. 维护成本:当产品类变化时,需要同步修改Builder

建造者模式与工厂模式的区别

虽然建造者模式和工厂模式都是创建型模式,但它们有明显区别:

  • 工厂模式 关注对象创建种类(what)
  • 建造者模式 关注复杂对象构建过程(how)

工厂用于创建整个对象,而建造者关注对象各个部分的创建过程和装配顺序。

建造者模式变体:自引用泛型流畅接口

这种高级变体使用泛型保持链式调用时的类型安全:

java 复制代码
public class Email {
    // 邮件属性
    private final String from;
    private final List<String> to;
    private final String subject;
    private final String body;
    private final List<String> attachments;
    
    private Email(Builder builder) {
        this.from = builder.from;
        this.to = new ArrayList<>(builder.to);
        this.subject = builder.subject;
        this.body = builder.body;
        this.attachments = new ArrayList<>(builder.attachments);
    }
    
    // 泛型Builder基类
    public static class Builder<T extends Builder<T>> {
        private String from;
        private List<String> to = new ArrayList<>();
        private String subject = "";
        private String body = "";
        private List<String> attachments = new ArrayList<>();
        
        // 自引用泛型类型转换
        @SuppressWarnings("unchecked")
        protected final T self() {
            return (T) this;
        }
        
        public T from(String from) {
            this.from = from;
            return self();
        }
        
        public T to(String address) {
            this.to.add(address);
            return self();
        }
        
        public T subject(String subject) {
            this.subject = subject;
            return self();
        }
        
        public T body(String body) {
            this.body = body;
            return self();
        }
        
        public T attachment(String attachment) {
            this.attachments.add(attachment);
            return self();
        }
        
        public Email build() {
            validateRequiredFields();
            return new Email(this);
        }
        
        private void validateRequiredFields() {
            if (from == null || from.isEmpty()) {
                throw new IllegalStateException("发件人不能为空");
            }
            if (to.isEmpty()) {
                throw new IllegalStateException("收件人不能为空");
            }
        }
    }
    
    // 具体Builder
    public static class EmailBuilder extends Builder<EmailBuilder> {
        // 不需要额外代码,因为基类已实现了所有功能
    }
    
    // 便捷的静态工厂方法
    public static EmailBuilder builder() {
        return new EmailBuilder();
    }
    
    @Override
    public String toString() {
        return "Email{" +
                "from='" + from + '\'' +
                ", to=" + to +
                ", subject='" + subject + '\'' +
                ", body='" + body + '\'' +
                ", attachments=" + attachments +
                '}';
    }
}

建造者模式最佳实践

  1. 使用场景选择:对象参数较多或构建过程复杂时使用
  2. 参数验证 :在build()方法中进行完整性校验
  3. 必选与可选分离:通过构造函数传入必选参数
  4. 不可变对象:建造者模式是创建不可变对象的好方法
  5. 链式API设计:返回this支持流畅接口
  6. 避免过早优化:简单对象不需要建造者模式
  7. 使用嵌套静态类:使Builder成为产品的静态内部类

建造者模式小结

建造者模式是一种强大的创建型设计模式,它通过分离复杂对象的构建过程与表示,使得创建过程更加灵活和可控。它特别适合于有多个参数选项的复杂对象创建,可以提高代码的可读性和可维护性。

在实际应用中,许多现代API和框架都采用了建造者模式的变体来提供流畅的接口。掌握这一模式有助于我们设计出更易用、更灵活的API,并解决对象创建中的复杂性问题。

无论是创建不可变对象,还是设计流畅的API,建造者模式都是一种值得掌握的重要设计模式。

相关推荐
周努力.10 小时前
设计模式之中介者模式
设计模式·中介者模式
yangyang_z1 天前
【C++设计模式之Template Method Pattern】
设计模式
源远流长jerry1 天前
常用设计模式
设计模式
z26373056111 天前
六大设计模式--OCP(开闭原则):构建可扩展软件的基石
设计模式·开闭原则
01空间1 天前
设计模式简述(十八)享元模式
设计模式·享元模式
秋名RG2 天前
深入理解设计模式之原型模式(Prototype Pattern)
设计模式·原型模式
Li小李同学Li2 天前
设计模式【cpp实现版本】
单例模式·设计模式
周努力.2 天前
设计模式之状态模式
设计模式·状态模式
268572592 天前
Java 23种设计模式 - 行为型模式11种
java·开发语言·设计模式
摘星编程3 天前
并发设计模式实战系列(19):监视器(Monitor)
设计模式·并发编程