Java设计模式-建造者模式

Java 的多个设计模式中,最易理解的应该就属 建造者模式 了,虽说看似很简单容易理解,但是却是很好的实践方式。
在平常的开发中,也有很多地方可以用到,让代码也是变得更加具有可读性和可维护性。

建造者模式的定义

什么是建造者模式呢?

网上查一下,如是说:

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

看起来还是有点抽象。其实通俗一点的说,建造者模式就是将一个复杂的对象的一系列属性的设置分为多个步骤来一步一步的来设置它的一系列属性,最终构建出这个复杂的对象。

建造者模式的场景

建造者模式就是将原本冗长的对象属性设置,转为使用清晰的明了的步骤来设置。

在我们平时编码的时候,总会遇到一些属性比较多,而且有嵌套对象的的对象,这个时候,如果使用常规的方式去构建这个对象,我们需要一个一个属性的去 set 它的属性。

如果说是字段不多还好,但是如果是有很多的字段,还有嵌套对象,那是不是感觉要崩溃。

还有一个就是,不知道大家遇到过,一个对象的构造方法参数一大堆,在 new 这个对象的时候,设置参数写着写着都不知道这个参数到底是干嘛的了,这样就很容易出错,毕竟如果是类型但是含义完全不同的字段,你设置错了也不会报错,但最终的结果却会是大相径庭。而且代码的可读性也是大大的降低了。

遇到这种情况的时候,我们就应该要想想,需要怎么做才能够减少出错的概率,并且提升代码的可读性和代码的可维护性。这个时候建造者模式就应该是个不二之选了。

建造者模式的例子

这里我们使用一个下单的场景来举例。

比如一个订单对象,包含了订单数据信息,收货人信息,地址信息,商品信息,促销信息,物流信息,支付信息。

在下单的时候,我们需要将各种信息组装到订单中,其中就包含了很多的字段,还有嵌套的对象,这里我们就可以采用建造者模式来一步一步的构建出一个完整的订单对象。

show code

订单对象对象包含了以下的字段信息:

@Data
public class Order {

    /**
     * 订单id
     */
    private Long id;

    /**
     * 订单创建时间
     */
    private Timestamp createTime;

    /**
     * 订单更新时间
     */
    private Timestamp updateTime;

    /**
     * 订单号
     */
    private String orderCode;

    /**
     * 订单状态
     */
    private OrderStatus orderStatus;

    /**
     * 未支付订单过期时间
     */
    private Timestamp expireAt;

    /**
     * 订单用户信息
     */
    private OrderUser orderUser;

    /**
     * 订单物流信息
     */
    private OrderDelivery orderDelivery;

    /**
     * 订单支付信息
     */
    private OrderPayment orderPayment;

    /**
     * 订单商品信息
     */
    private List<OrderProduct> orderProducts;

    /**
     * 订单促销信息
     */
    private List<OrderPromotion> orderPromotions;

    /**
     * 订单收货地址信息
     */
    private OrderAddress orderAddress;
}

上面只是简单的列了下订单的信息,真实的场景肯定会有更多的字段。下面我们就使用建造者模式来构建这个订单信息。

创建一个名为 OrderBuilder 的订单信息构造器。

public class OrderBuilder {

    /**
     * 将需要构建的 order 对象作为全局变量
     * 在一步一步构建完成之后返回该对象
     */
    private Order order;

    /**
     * 使构造器私有化
     * 不让使用者使用 new 来创建构造器,而是通过 {@link OrderBuilder#newBuilder()} 来创建构造器
     */
    private OrderBuilder() {
    }

    /**
     * 建造者模式的入口
     * 这里会初始化构造器和需要构造的order对象
     * 也可以根据自己的要做一些其他的操作
     *
     * @return 构造器本身,后面可以链式调用
     */
    public static OrderBuilder newBuilder() {
        OrderBuilder orderBuilder = new OrderBuilder();
        orderBuilder.order = new Order();

        return orderBuilder;
    }

    /**
     * 这里设置一些order的简单属性
     *
     * @param orderVo 前端传入的 order value object 对象
     * @return 构造器本身,后面可以链式调用
     */
    public OrderBuilder initOrder(OrderVo orderVo) {
        //这里根据自己的需要做一些简单的设值操作
        //...
        return this;
    }

    /**
     * 设置订单用户信息
     *
     * @param orderUser 前端传入的订单用户 value object 对象
     * @return 构造器本身,后面可以链式调用
     */
    public OrderBuilder setOrderUser(OrderUserVo orderUser) {
        //...
        return this;
    }

    /**
     * 设置订单用户收货地址信息
     *
     * @param orderAddress 前端传入的订单用户收货地址 value object 对象
     * @return 构造器本身,后面可以链式调用
     */
    public OrderBuilder setOrderAddress(OrderAddressVo orderAddress) {
        //...
        return this;
    }

    /**
     * 设置订单物流信息
     *
     * @param orderDelivery 前端传入的订单物流 value object 对象
     * @return 构造器本身,后面可以链式调用
     */
    public OrderBuilder setOrderDelivery(OrderDeliveryVo orderDelivery) {
        //...
        return this;
    }

    /**
     * 设置订单商品信息
     *
     * @param orderProducts 前端传入的订单商品 value object 对象集合
     * @return 构造器本身,后面可以链式调用
     */
    public OrderBuilder setOrderProducts(List<OrderProductVo> orderProducts) {
        //...
        return this;
    }

    /**
     * 设置订单促销信息
     *
     * @param orderPromotions 前端传入的订单促销信息 value object 对象集合
     * @return 构造器本身,后面可以链式调用
     */
    public OrderBuilder setOrderPromotions(List<OrderPromotionVo> orderPromotions) {
        //...
        return this;
    }

    /**
     * 设置订单支付信息
     *
     * @param orderPayment 前端传入的订单支付信息 value object 对象集合
     * @return 构造器本身,后面可以链式调用
     */
    public OrderBuilder setOrderPayment(OrderPaymentVo orderPayment) {
        //...
        return this;
    }

    /**
     * 返回最终构建完成的订单对象
     *
     * @return 返回最终构建完成的订单对象
     */
    public Order build() {
        return this.order;
    }

}

上面的订单信息构造器创建好了,我们在构建订单对象的时候,就显得特别的简洁了,只需要创建构造器和根据需要调用构造器方法设值就行了。

Order order = OrderBuilder.newBuilder()
                .initOrder(orderVo)
                .setOrderUser(orderUserVo)
                .setOrderAddress(orderAddressVo)
                .setOrderProducts(orderProducts)
                .setOrderPromotions(orderPromotions)
                .setOrderPayment(orderPaymentVo)
                .build();

尾巴

建造者模式就说完了,有错误的请留言指出,文笔不是很好,请多包涵。

推荐阅读更多精彩内容