说说建造者模式

一、建造者模式概述

建造者模式是一种创建型设计模式,旨在提供一种灵活的解决方案,用于创建复杂的对象,什么是复杂对象呢?简单来说,复杂对象是指那些包含多个成员属性的对象,这些成员属性也称为部件或零件。它通过将对象的构建过程和表示分离,使得同样的构建过程可以创建不同的表示。

二、传统创建对象方式的痛点

  1. 构造方法参数过多,示例代码如下:

    java 复制代码
    Order order = new Order("202509250001", 9527, "2025-09-25 00:00:00", 100.00, "待支付", "微信支付");

    大家可以看到,这个构造方法的参数太多了,写着写着可能你都分不清哪个参数对应哪个属性。可能你将"微信支付"赋值给了支付状态属性,将"待支付"赋值给了支付方式属性都没发现有问题,因为这两个字段都是字符串类型,编译器并不会报错。只要参数超过5个,调用者都会陷入参数地狱。

二、建造者模式的结构

建造者模式的四个角色:

  1. Product:产品类,最终要构建的复杂对象。
  2. Builder:抽象建造者,定义构建步骤的接口。
  3. ConcreteBuilder:具体建造者,实现抽象建造者的接口,实现构建步骤并返回产品。
  4. Direct:指挥者(可选),控制构建过程。

三、示例

很多系统中都会有下订单这个操作,这个订单表里面是包含了很多字段的,比如订单号、用户id、下单时间、订单总金额、订单状态、支付方式等多个可选部件,建造者模式可以灵活地进行组装,下面直接上代码。

传统版本

1.产品类

java 复制代码
public class Order {
    private String orderNum;
    private int userId;
    private Date orderTime;
    private BigDecimal totalPrice;
    private String status;
    private String paymentMethod;

    public String getOrderNum() {
        return orderNum;
    }

    public void setOrderNum(String orderNum) {
        this.orderNum = orderNum;
    }

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public LocalDateTime getOrderTime() {
        return orderTime;
    }

    public void setOrderTime(Date orderTime) {
        this.orderTime = orderTime;
    }

    public BigDecimal getTotalPrice() {
        return totalPrice;
    }

    public void setTotalPrice(BigDecimal totalPrice) {
        this.totalPrice = totalPrice;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getPaymentMethod() {
        return paymentMethod;
    }

    public void setPaymentMethod(String paymentMethod) {
        this.paymentMethod = paymentMethod;
    }

    @Override
    public String toString() {
        return "Order{" +
                "orderNum='" + orderNum + '\'' +
                ", userId=" + userId +
                ", orderTime=" + orderTime +
                ", totalPrice=" + totalPrice +
                ", status='" + status + '\'' +
                ", paymentMethod='" + paymentMethod + '\'' +
                '}';
    }
}

2.抽象建造者

java 复制代码
public interface OrderBuilder {
    void buildOrderNum(String orderNum);
    void buildUserId(int userId);
    void buildOrderTime(Date orderTime);
    void buildTotalPrice(BigDecimal totalPrice);
    void buildStatus(String status);
    void buildPaymentMethod(String paymentMethod);

    /**
     * 返回完整对象
     */
    Order build();
}

抽象建造者中还声明了一个得到产品建造后结果的方法build。

3.具体建造者

java 复制代码
public class ConcreteOrderBuilder implements OrderBuilder{

    private Order order = new Order();
    
    @Override
    public void buildOrderNum(String orderNum) {
        order.setOrderNum(orderNum);
    }
    @Override
    public void buildUserId(int userId) {
        order.setUserId(userId);
    }
    @Override
    public void buildOrderTime(Date orderTime) {
        order.setOrderTime(orderTime);
    }
    @Override
    public void buildTotalPrice(BigDecimal totalPrice) {
        order.setTotalPrice(totalPrice);
    }
    @Override
    public void buildStatus(String  status) {
        order.setStatus(status);
    }
    @Override
    public void buildPaymentMethod(String paymentMethod) {
        order.setPaymentMethod(paymentMethod);
    }

    public Order build() {
        return order;
    }
}

4.指挥者

java 复制代码
public class Director {
    private OrderBuilder orderBuilder;
    public Director(OrderBuilder orderBuilder) {
        this.orderBuilder = orderBuilder;
    }

    /**
     * 构建并返回完整对象
     */
    public Order construct(String orderNum, int userId, Date orderTime, BigDecimal totalPrice, String status, String paymentMethod) {
        orderBuilder.buildOrderNum(orderNum);
        orderBuilder.buildUserId(userId);
        orderBuilder.buildOrderTime(orderTime);
        orderBuilder.buildTotalPrice(totalPrice);
        orderBuilder.buildStatus(status);
        orderBuilder.buildPaymentMethod(paymentMethod);
        return orderBuilder.build();
    }
}

5.客户端

java 复制代码
public class Client {
    public static void main(String[] args) {
        //使用指挥者
        OrderBuilder builder =  new ConcreteOrderBuilder();
        Director director = new Director(builder);
        Order order = director.construct("202509250001", 9527,new Date(), new BigDecimal(100), "待支付", "微信支付");

        //或者直接使用具体建造者
        OrderBuilder builder1 = new ConcreteOrderBuilder();
        builder1.buildOrderNum("202509250001");
        builder1.buildUserId(9527);
        builder1.buildOrderTime(new Date());
        builder1.buildTotalPrice(new BigDecimal(100));
        builder1.buildStatus("待支付");
        builder1.buildPaymentMethod("微信支付");
        Order order1 = builder1.build();
    }
}

链式调用版本

java 复制代码
public class Order {
    private String orderNum;
    private int userId;
    private Date orderTime;
    private BigDecimal totalPrice;
    private String status;
    private String paymentMethod;

    //私有化构造器,外部不能new,只能通过Builder创建
    private Order(String orderNum, int userId, Date orderTime, BigDecimal totalPrice, String status, String paymentMethod) {
        this.orderNum = orderNum;
        this.userId = userId;
        this.orderTime = orderTime;
        this.totalPrice = totalPrice;
        this.status = status;
        this.paymentMethod = paymentMethod;
    }

    @Override
    public String toString() {
        return "Order{" +
                "orderNum='" + orderNum + '\'' +
                ", userId=" + userId +
                ", orderTime=" + orderTime +
                ", totalPrice=" + totalPrice +
                ", status='" + status + '\'' +
                ", paymentMethod='" + paymentMethod + '\'' +
                '}';
    }

    public static class Builder {
        private String orderNum;
        private int userId;
        private Date orderTime;
        private BigDecimal totalPrice;
        private String status;
        private String paymentMethod;
        public Builder buildOrderNum(String orderNum) {
            this.orderNum = orderNum;
            return this;
        }

        public Builder buildUserId(int userId) {
            this.userId = userId;
            return this;
        }
        public Builder buildOrderTime(Date orderTime) {
            this.orderTime = orderTime;
            return this;
        }
        public Builder buildTotalPrice(BigDecimal totalPrice) {
            this.totalPrice = totalPrice;
            return this;
        }
        public Builder buildStatus(String status) {
            this.status = status;
            return this;
        }
        public Builder buildPaymentMethod(String paymentMethod) {
            this.paymentMethod = paymentMethod;
            return this;
        }
        public Order build() {
            //这里可以添加校验逻辑
            if(status == null){
                throw new IllegalStateException("订单状态不能为空");
            }
            return new Order(orderNum, userId, orderTime, totalPrice, status, paymentMethod);
        }
    }
}

建造者类

java 复制代码
public class ConcreteOrderBuilder {

    private Order order = new Order();

    public ConcreteOrderBuilder buildOrderNum() {
        order.setOrderNum("202509250001");
        return this;
    }

    public ConcreteOrderBuilder buildUserId() {
        order.setUserId(9527);
        return this;
    }

    public ConcreteOrderBuilder buildOrderTime() {
        order.setOrderTime(LocalDateTime.now());
        return this;
    }

    public ConcreteOrderBuilder buildTotalPrice() {
        order.setTotalPrice(new BigDecimal(100));
        return this;
    }

    public ConcreteOrderBuilder buildStatus() {
        order.setStatus("待支付");
        return this;
    }

    public ConcreteOrderBuilder buildPaymentMethod() {
        order.setPaymentMethod("微信支付");
        return this;
    }

    public Order getResult() {
        return order;
    }
}

客户端

java 复制代码
public class Client {
    public static void main(String[] args) {
        //使用链式调用来创建对象,链式调用提升了代码可读性。
        Order order = new Order.Builder()
                .buildOrderNum("202509250001")
                .buildOrderTime(new Date())
                .buildPaymentMethod("微信支付")
                .buildStatus("1")
                .buildTotalPrice(BigDecimal.valueOf(100.00))
                .buildUserId(9527)
                .build();
        System.out.println(order);
    }
}

两种版本对比:

通过传统版本中,Director指挥者类中的construct方法可以看到,这种方式比较适合构建过程固定的场景。而链式调用版本,通过返回this实现链式调用,适合构建过程灵活、需要动态配置的场景。

如果你的项目中有使用到Lombok,那么你应该知道它提供了一个@Builder注解,Lombok的@Builder注解通过自动生成构建者模式代码实现链式调用,其核心机制是为目标类创建内部静态Builder类,每个属性对应生成同名链式方法(返回Builder实例),最终通过build()方法完成对象构建。(Lombok在编译期修改AST,生成包含完整链式方法的静态内部类。)

总结

当你的实体类满足以下条件时,可以考虑使用建造者模式:

  1. 实体类中字段太多,比如超过5个。
  2. 存在参数校验逻辑,比如上述例子中的userId字段要求必填,可以在build方法中加入校验逻辑。
相关推荐
用户4099322502122 小时前
PostgreSQL UPDATE语句怎么玩?从改邮箱到批量更新的避坑技巧你都会吗?
后端·ai编程·trae
我是谁的程序员2 小时前
前端调试工具有哪些?常用前端调试工具推荐、前端调试工具对比
后端
一直_在路上2 小时前
Go语言架构实践:构建临床ePRO高性能内存数据网格,应对海量并发挑战
后端
一 乐2 小时前
智慧外贸平台|基于Java+vue的智慧外贸平台系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·外贸服务系统
一叶飘零_sweeeet3 小时前
打造高可用系统通知架构:站内信、短信、邮件、推送全方案解析
java·系统通知
SimonKing3 小时前
🐔老乡鸡把菜谱在GitHub开源了,还说要给程序员发会员卡
java·后端·程序员
Q_Q19632884753 小时前
python+django/flask二手物品交易系统 二手商品发布 分类浏览 在线沟通与订单管理系统java+nodejs
java·spring boot·python·django·flask·node.js·php
IT_陈寒3 小时前
⚡️Vite 5重磅升级:10个性能优化技巧让你的项目提速300%!🚀
前端·人工智能·后端
yujkss3 小时前
23种设计模式之【责任链模式】-核心原理与 Java 实践
java·设计模式·责任链模式