设计模式之建造者模式

简介: 建造者模式同样是创建型设计模式的一种,用于解决复杂对象的创建问题。

建造者模式同样是创建型设计模式的一种,用于解决复杂对象的创建问题。


为什么需要建造者模式


为了得到一个对象,通常情况下我们调用构造方法然后再配合 set 方法做一些初始化工作即可。假定我们现在有一个传感器,传感器的名称和类型不能为空、客户ID可选、如果客户ID不为空时安装时间也不能为空,反应到类的代码如下。


建造者模式同样是创建型设计模式的一种,用于解决复杂对象的创建问题。
为什么需要建造者模式
为了得到一个对象,通常情况下我们调用构造方法然后再配合 set 方法做一些初始化工作即可。假定我们现在有一个传感器,传感器的名称和类型不能为空、客户ID可选、如果客户ID不为空时安装时间也不能为空,反应到类的代码如下。
————————————————
版权声明:本文为CSDN博主「大鹏cool」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zzuhkp/article/details/11645641


为了满足传感器各属性的限制,我们定义了三个构造方法,为了复用代码,我们的实现中参数少的构造方法会调用参数多的构造方法。当前只有三个构造方法还可以接受,如果以后需要再次扩展,如温度传感器需要配置报警的最低温度和最高温度,我们还需要为构造方法增加新的参数,具体如下。


public class Sensor {
    private String name;
    private String type;
    private Integer customerId;
    private Date installTime;
    private Double lower;
    private Double upper;
    public Sensor(String name, String type, Integer customerId, Date installTime, Double lower, Double upper) {
        ... 省略部分代码
        if ((lower != null && upper == null) || (upper != null && lower == null)) {
            throw new IllegalArgumentException("报警温度有误");
        }
        if (lower != null && upper != null && lower > upper) {
            throw new IllegalArgumentException("报警温度有误");
        }
        this.name = name;
        this.type = type;
        this.customerId = customerId;
        this.installTime = installTime;
        this.lower = lower;
        this.upper = upper;
    }
}


发现问题了吗?类的构造方法参数不断的增加,最终导致可读性极差,很容易传入错误的参数,使用者必须阅读相关注释或代码才能确实使用哪个构造方法。


那怎么解决这个问题呢?按照通常的思路,调用构造方法后再调 set 方法,我们只把传感器必须的属性作为构造方法参数,其他的属性通过 set 方法设置即可。代码如下。


        Sensor sensor = new Sensor("温度传感器", "温度");
        sensor.setInstallTime(new Date());
        sensor.setCustomerId(1);


但是问题又来了,我们是需要进行参数校验的,对于上述的场景设置了客户ID后则必须设置安装时间,我们无法保证设置安装时间方法、设置客户ID方法的调用顺序,也就是说对于有依赖关系的属性现在我们无法进行参数校验。怎么办呢?为了保证构造方法参数不断扩展又需要进行参数校验,建造者模式就出现了。


如何实现一个建造者模式


使用建造者模式解决上述问题,代码如下。


public class Sensor {
    private String name;
    private String type;
    private Integer customerId;
    private Date installTime;
    private Double lower;
    private Double upper;
    private Sensor(Build build) {
        this.name = build.name;
        this.type = build.type;
        this.customerId = build.customerId;
        this.installTime = build.installTime;
        this.lower = build.lower;
        this.upper = build.upper;
    }
    public static class Build {
        private String name;
        private String type;
        private Integer customerId;
        private Date installTime;
        private Double lower;
        private Double upper;
        public String getName() {
            return name;
        }
        public Build setName(String name) {
            this.name = name;
            return this;
        }
        public String getType() {
            return type;
        }
        public Build setType(String type) {
            this.type = type;
            return this;
        }
        public Integer getCustomerId() {
            return customerId;
        }
        public Build setCustomerId(Integer customerId) {
            this.customerId = customerId;
            return this;
        }
        public Date getInstallTime() {
            return installTime;
        }
        public Build setInstallTime(Date installTime) {
            this.installTime = installTime;
            return this;
        }
        public Double getLower() {
            return lower;
        }
        public Build setLower(Double lower) {
            this.lower = lower;
            return this;
        }
        public Double getUpper() {
            return upper;
        }
        public Build setUpper(Double upper) {
            this.upper = upper;
            return this;
        }
        public Sensor build() {
            if (this.name == null || this.name.isEmpty()) {
                throw new IllegalArgumentException("名称不能为空");
            }
            if (this.type == null || this.type.isEmpty()) {
                throw new IllegalArgumentException("类型不能为空");
            }
            if (this.customerId != null) {
                if (this.installTime != null && this.installTime.compareTo(new Date()) > 0) {
                    throw new IllegalArgumentException("安装时间有误");
                }
            }
            if ((this.lower != null && this.upper == null) || (this.upper != null && this.lower == null)) {
                throw new IllegalArgumentException("报警温度有误");
            }
            if (this.lower != null && this.upper != null && this.lower > this.upper) {
                throw new IllegalArgumentException("报警温度有误");
            }
            Sensor sensor = new Sensor(this);
            return sensor;
        }
    }
}


使用方此时创建传感器类实例的代码如下。


Sensor sensor = new Sensor.Build().setName("温度传感器").setType("温度").setCustomerId(1).setInstallTime(new Date()).build();


我们将设置对象属性的代码转移到了建造者类中,然后在建造者类的 build 方法中完成了参数的校验。


总结

建造者模式用于解决复杂对象创建的问题,针对构造方法参数过长和具有依赖关系的参数校验问题,将参数设置的代码转移到建造者类,并通过建造者类的 build 方法完成存在依赖关系的参数校验。实现一个建造者模式通常的步骤如下。


在实体类中创建一个静态内部类 XxxBuilder,属性和实体类保持一致。

实体类提供一个私有的仅有一个类型为静态内部类的参数。

静态内部类的 setter 方法返回静态内部类实例,便于链式调用。

静态内部类提供 build 方法,用于参数校验及实例化实体类。


目录
相关文章
|
3月前
|
设计模式 Java
【设计模式系列笔记】建造者模式
建造者模式是一种创建型设计模式,用于将复杂对象的构建与其表示分离,使构建过程可定制。关键元素包括产品类(定义要构建的对象)、建造者接口(定义构建方法)、具体建造者类(实现构建过程)和指导者类(负责构建过程)。通过建造者模式,客户端可以灵活地创建具有不同表示的复杂对象,提高代码的可读性和可维护性,尤其适用于构建过程复杂且包含多个可选部分的情况。
122 1
|
3月前
|
设计模式 安全 Java
构建未来应用:Java设计模式 - 建造者模式(Builder)在现代编程中的应用
【4月更文挑战第7天】建造者模式是提升代码质量的关键,尤其在复杂环境中。它分步骤构建对象,将构建与表示分离,适用于UI构建、数据模型组装、配置文件解析和网络请求构造等场景。最佳实践包括明确构建步骤、提供默认值、支持链式调用和确保线程安全。然而,过多步骤、不一致状态和性能问题是使用时需注意的问题。掌握建造者模式对于现代编程至关重要。
53 3
|
1天前
|
设计模式 XML 存储
【四】设计模式~~~创建型模式~~~建造者模式(Java)
文章详细介绍了建造者模式(Builder Pattern),这是一种创建型设计模式,用于将复杂对象的构建与其表示分离,允许分步骤创建一个复杂的对象而无需指定其内部的具体构造细节。通过定义抽象建造者、具体建造者、指挥者和产品角色,建造者模式允许通过相同的构建过程创建不同的产品表示,提高了系统的灵活性和扩展性。
|
2月前
|
设计模式 算法
建造者模式-大话设计模式
建造者模式-大话设计模式
19 1
|
1月前
|
设计模式 JavaScript
js设计模式【详解】—— 建造者模式
js设计模式【详解】—— 建造者模式
22 0
|
3月前
|
设计模式 uml
大话设计模式(3)——造物者一般的建造者模式
大话设计模式(3)——造物者一般的建造者模式
29 1
大话设计模式(3)——造物者一般的建造者模式
|
2月前
|
设计模式
设计模式-05建造者模式(Builder Pattern)
设计模式-05建造者模式(Builder Pattern)
|
2月前
|
设计模式 Java
Java设计模式:建造者模式之经典与流式的三种实现(四)
Java设计模式:建造者模式之经典与流式的三种实现(四)
|
2月前
|
设计模式 Java
Java设计模式之建造者模式详解
Java设计模式之建造者模式详解
|
2月前
|
设计模式 Java
设计模式之建造者模式
设计模式之建造者模式