建造者模式

简介:

Builder 模式,中文翻译为建造者模式或者构建者模式,也有人叫它生成器模式

创建者模式主要包含以下四个角色:

  1. 产品(Product):表示将要被构建的复杂对象。
  2. 抽象创建者(Abstract Builder):定义构建产品的接口,通常包含创建和获取产品的方法。
  3. 具体创建者(Concrete Builder):实现抽象创建者定义的接口,为产品的各个部分提供具体实现。
  4. 指挥者(Director):负责调用具体创建者来构建产品的各个部分,控制构建过程。
为什么需要建造者模式?
需求一、根据复杂的配置项进行定制化构建

首先,我们先看一个mybaits中经典的案例,这个案例中使用了装饰器和创建者设计模式:

public class CacheBuilder {
    private final String id;
    private Class<? extends Cache> implementation;
    private final List<Class<? extends Cache>> decorators;
    private Integer size;
    private Long clearInterval;
    private boolean readWrite;
    private Properties properties;
    private boolean blocking;

    public CacheBuilder(String id) {
        this.id = id;
        this.decorators = new ArrayList<>();
    }

    public CacheBuilder size(Integer size) {
        this.size = size;
        return this;
    }

    public CacheBuilder clearInterval(Long clearInterval) {
        this.clearInterval = clearInterval;
        return this;
    }

    public CacheBuilder blocking(boolean blocking) {
        this.blocking = blocking;
        return this;
    }

    public CacheBuilder properties(Properties properties) {
        this.properties = properties;
        return this;
    }

    public Cache build() {
        setDefaultImplementations();
        Cache cache = newBaseCacheInstance(implementation, id);
        setCacheProperties(cache);
        // 根据配置的装饰器对原有缓存进行增强,如增加淘汰策略等
        if (PerpetualCache.class.equals(cache.getClass())) {
            for (Class<? extends Cache> decorator : decorators) {
                cache = newCacheDecoratorInstance(decorator, cache);
                setCacheProperties(cache);
            }
            cache = setStandardDecorators(cache);
        } else if (!LoggingCache.class.isAssignableFrom(cache.getClass())) {
            cache = new LoggingCache(cache);
        }
        return cache;
    }
}

我们总结这个案例中的几个特点:

1、参数有必填项id,有很多可选填的内容,通常必选项id通过构造器传入,可选项通过方法传递。

2、真正的构建过程需要调用build方法,构建时需要根据已配置的成员变量的内容选择合适的装饰器,对目标cache进行增强。

需求二、实现不可变对象

创建者设计模式(Builder Design Pattern)可以实现不可变对象,即一旦创建完成,对象的状态就不能改变。这有助于保证对象的线程安全和数据完整性。下面是一个使用创建者设计模式实现的不可变对象的Java示例:

public final class ImmutablePerson {
    private final String name;
    private final int age;
    private final String address;

    private ImmutablePerson(Builder builder) {
        this.name = builder.name;
        this.age = builder.age;
        this.address = builder.address;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String getAddress() {
        return address;
    }

    public static class Builder {
        private String name;
        private int age;
        private String address;

        public Builder() {
        }

        public Builder setName(String name) {
            this.name = name;
            return this;
        }

        public Builder setAge(int age) {
            this.age = age;
            return this;
        }

        public Builder setAddress(String address) {
            this.address = address;
            return this;
        }

        public ImmutablePerson build() {
            return new ImmutablePerson(this);
        }
    }
}

在这个例子中,ImmutablePerson 类具有三个属性:nameage 和 address。这些属性都是 final 的,一旦设置就不能更改。ImmutablePerson 的构造函数是私有的,外部无法直接创建该类的实例。要创建一个 ImmutablePerson 实例,需要使用内部的 Builder 类。通过连续调用 Builder 类的方法,我们可以为 ImmutablePerson 设置属性。最后,通过调用 build() 方法,我们创建一个具有指定属性的不可变 ImmutablePerson 实例。

实际上,使用建造者模式创建对象,还能避免对象存在无效状态。我再举个例子解释一下。比如我们定义了一个长方形类,如果不使用建造者模式,采用先创建后 set 的方式,那就会导致在第一个 set 之后,对象处于无效状态。具体代码如下所示:

Rectangle r = new Rectange(); // r is valid
r.setWidth(2); // r is valid
r.setHeight(3); // r is invalid

为了避免这种无效状态的存在,我们就需要使用构造函数一次性初始化好所有的成员变量。如果构造函数参数过多,我们就需要考虑使用建造者模式,先设置建造者的变量,然后再一次性地创建对象,让对象一直处于有效状态。

实际上,如果我们并不是很关心对象是否有短暂的无效状态,也不是太在意对象是否是可变的。比如,对象只是用来映射数据库读出来的数据,那我们直接暴露 set() 方法来设置类的成员变量值是完全没问题的。而且,使用建造者模式来构建对象,代码实际上是有点重复的。

相关推荐

  1. 建造模式(Builder)

    2024-04-24 14:02:03       59 阅读
  2. 建造模式

    2024-04-24 14:02:03       40 阅读
  3. 建造模式

    2024-04-24 14:02:03       50 阅读
  4. 建造模式(Builder)

    2024-04-24 14:02:03       46 阅读
  5. 建造模式

    2024-04-24 14:02:03       46 阅读
  6. 建造模式

    2024-04-24 14:02:03       40 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-24 14:02:03       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-24 14:02:03       106 阅读
  3. 在Django里面运行非项目文件

    2024-04-24 14:02:03       87 阅读
  4. Python语言-面向对象

    2024-04-24 14:02:03       96 阅读

热门阅读

  1. GB/T 22271.2-2021聚甲醛POM模塑和挤出材料检测

    2024-04-24 14:02:03       40 阅读
  2. 去掉 pom依赖里引入模块 不要的 @Bean @Configuration

    2024-04-24 14:02:03       37 阅读
  3. Ant-design中表单多级对象做嵌套表单校验

    2024-04-24 14:02:03       38 阅读
  4. springboot @Validated的概念以及实战

    2024-04-24 14:02:03       39 阅读
  5. MySQL数据库-左右外链接

    2024-04-24 14:02:03       32 阅读
  6. 数据库审计

    2024-04-24 14:02:03       30 阅读
  7. keyguardManager.isKeyguardLocked()在oppo手机上返回错误

    2024-04-24 14:02:03       35 阅读
  8. LeetCode 0039.组合总和:回溯 + 剪枝

    2024-04-24 14:02:03       35 阅读
  9. 神经网络进阶学习文章(一)

    2024-04-24 14:02:03       41 阅读