创建型设计模式-3.建造者设计模式

创建型设计模式-2.建造者设计模式

一、简介

建造者设计模式(Builder Pattern)是一种创建型设计模式,它专注于逐步构建复杂对象 。它将对象的构建过程与其表示分离,允许相同的构建过程创建不同的表示形式。该模式的目标是简化对象的构建过程,并提供灵活性和可扩展性。

二、核心思想

Builder设计模式的核心思想是将对象的构建过程从其实际表示中解耦。通常情况下,一个对象的构建过程是复杂且多步骤的,使用Builder模式可以将这些步骤分解为独立的方法,从而使得构建过程更加灵活和可控。

三、组成和基本流程

Builder设计模式包含以下几个主要组成部分:

  1. Director(指导者):负责控制对象的构建过程,按照一定的顺序调用Builder的方法来构建对象。
  2. Builder(构建者):定义构建对象的接口,包含各个构建步骤的方法。
  3. ConcreteBuilder(具体构建者):实现Builder接口,负责具体的构建逻辑,并返回构建完成的对象。
  4. Product(产品):表示最终构建完成的对象,通常具有复杂的内部结构。

Builder设计模式的基本流程如下:

  1. 定义一个Builder接口,其中包含各个构建步骤的方法。
  2. 创建具体的Builder类,实现Builder接口,并实现各个构建步骤的具体逻辑。
  3. 创建一个Director类,它包含一个Builder对象作为成员变量。通过调用Builder的方法,按照特定的顺序构建对象。
  4. 最终调用Builder的一个方法返回构建完成的对象。

下列是一个简单的建造者设计模式的例子,这段代码演示了如何使用建造者设计模式创建一个电脑对象。

  • 首先,我们定义了一个Computer类,它具有一些属性(processor、memory、hardDisk、monitor)以及对应的设置方法。

  • 然后,我们定义了一个ComputerBuilder接口,其中包含了构建电脑对象所需的方法(buildProcessor、buildMemory、buildHardDisk、buildMonitor)以及获取构建完成的电脑对象的方法getComputer()。

  • 接着,我们实现了一个BasicComputerBuilder类,它是ComputerBuilder接口的具体实现。在BasicComputerBuilder类中,我们实例化了一个Computer对象,并实现了构建电脑各个部件的方法。

  • 之后,我们创建了一个ComputerDirector类,它负责指导建造过程。通过调用ComputerBuilder的方法,按照一定的顺序构建电脑对象,并返回构建完成的对象。

  • 最后,在Main类中,我们创建了一个BasicComputerBuilder对象作为建造者,创建了一个ComputerDirector对象作为指导者,然后通过指导者来构建电脑对象。最后,我们输出了构建完成的电脑对象的各个属性。

java 复制代码
class Computer {
    private String processor;
    private String memory;
    private String hardDisk;
    private String monitor;

    public void setProcessor(String processor) {
        this.processor = processor;
    }

    public void setMemory(String memory) {
        this.memory = memory;
    }

    public void setHardDisk(String hardDisk) {
        this.hardDisk = hardDisk;
    }

    public void setMonitor(String monitor) {
        this.monitor = monitor;
    }

    // 省略其他方法和属性的访问器
}

interface ComputerBuilder {
    void buildProcessor();
    void buildMemory();
    void buildHardDisk();
    void buildMonitor();
    Computer getComputer();
}

class BasicComputerBuilder implements ComputerBuilder {
    private Computer computer;

    public BasicComputerBuilder() {
        this.computer = new Computer();
    }

    public void buildProcessor() {
        computer.setProcessor("Basic Processor");
    }

    public void buildMemory() {
        computer.setMemory("4GB");
    }

    public void buildHardDisk() {
        computer.setHardDisk("500GB");
    }

    public void buildMonitor() {
        computer.setMonitor("15-inch");
    }

    public Computer getComputer() {
        return computer;
    }
}

class ComputerDirector {
    public Computer buildComputer(ComputerBuilder builder) {
        builder.buildProcessor();
        builder.buildMemory();
        builder.buildHardDisk();
        builder.buildMonitor();
        return builder.getComputer();
    }
}

public class Main {
    public static void main(String[] args) {
        ComputerBuilder builder = new BasicComputerBuilder();
        ComputerDirector director = new ComputerDirector();
        Computer computer = director.buildComputer(builder);

        System.out.println("Processor: " + computer.getProcessor());
        System.out.println("Memory: " + computer.getMemory());
        System.out.println("Hard Disk: " + computer.getHardDisk());
        System.out.println("Monitor: " + computer.getMonitor());
    }
}

在这个示例中,我们通过建造者模式逐步构建了一个电脑对象。指导者类控制了建造过程,而具体的建造者类负责实际构建对象。最终,我们可以获取到一个完整的电脑对象,并对其进行进一步操作。

四、使用场景

Builder设计模式适用于以下情况:

  • 当需要创建具有复杂内部结构的对象时,可以使用Builder模式将构建过程分解为多个简单步骤。
  • 当需要构建的对象存在不同的表示形式时,可以使用Builder模式来创建不同的表示。
  • 当需要在构建过程中灵活地添加或修改构建步骤时,可以使用Builder模式。
  • 实现不可变对象,可以使用Builder模式创建不可变对象。通过将建造者的构建方法设置为私有,并将需要的属性通过构造函数进行初始化,可以确保对象在构建后不可再修改。这样的对象可以提供更好的线程安全性和代码健壮性。

五、具体案例

在这个示例中,我们使用建造者设计模式创建了一个名为 ImmutablePerson 的不可变对象类。

  • ImmutablePerson 类中,属性 nameageaddress 被声明为 final,并且没有提供任何修改它们的方法。这样可以确保这些属性在对象创建后不可变。

  • 通过私有的构造方法 ImmutablePerson(Builder builder),我们将属性的值从 Builder 对象传递给了 ImmutablePerson 对象,并在构造方法内进行了赋值操作。这样,我们可以在构造对象时保证对象的属性值一致和不可变。

  • Builder 类是一个嵌套类,它提供了链式调用的方法来设置 ImmutablePerson 的属性值。每个方法都返回 Builder 对象本身,以便可以连续调用多个方法。最后,通过调用 build() 方法,我们可以创建并返回一个不可变的 ImmutablePerson 对象。

使用该示例,我们可以这样创建一个不可变的 ImmutablePerson 对象:

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);
        }
    }
    public static void main(String[] args) {
        // Usage example:
        ImmutablePerson person = new ImmutablePerson.Builder()
            .setName("John")
            .setAge(30)
            .setAddress("123 Street")
            .build();
    }
}

在这个示例中,我们通过链式调用 Builder 的方法设置属性的值,并最后调用 build() 方法来创建 ImmutablePerson 对象。一旦对象创建完成,它的属性就是不可变的,无法再修改。

这种方式提供了不可变对象的安全性和线程安全性,因为对象的状态无法在创建后被修改。不可变对象还可以更容易地进行缓存、共享和使用。


lombok例子:

在lombok中,我们使用@Builder注解会自动生成一个建造者模式的构建者类。下面是一个使用Lombok的@Builder注解的示例代码:

非常抱歉前面的回答中有些遗漏,确实是多了一些代码。以下是编译前和编译后的代码:

编译前的代码:

java 复制代码
@Builder
@Getter
@ToString
public class User {
    private String name;
    private Integer age;
    private String bobby;

    public static void main(String[] args) {
        User.UserBuilder builder = new UserBuilder();
        User user = builder.name("jack").age(18).bobby("rap").build();
        System.out.println("user = " + user);
    }
}

编译后的代码:

java 复制代码
public class User {
    private String name;
    private Integer age;
    private String bobby;

    public static void main(String[] args) {
        UserBuilder builder = new UserBuilder();
        User user = builder.name("jack").age(18).bobby("rap").build();
        System.out.println("user = " + user);
    }

    User(String name, Integer age, String bobby) {
        this.name = name;
        this.age = age;
        this.bobby = bobby;
    }

    public static UserBuilder builder() {
        return new UserBuilder();
    }

    public String getName() {
        return this.name;
    }

    public Integer getAge() {
        return this.age;
    }

    public String getBobby() {
        return this.bobby;
    }

    public String toString() {
        return "User(name=" + this.getName() + ", age=" + this.getAge() + ", bobby=" + this.getBobby() + ")";
    }

    public static class UserBuilder {
        private String name;
        private Integer age;
        private String bobby;

        UserBuilder() {
        }

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

        public UserBuilder age(Integer age) {
            this.age = age;
            return this;
        }

        public UserBuilder bobby(String bobby) {
            this.bobby = bobby;
            return this;
        }

        public User build() {
            return new User(this.name, this.age, this.bobby);
        }

        public String toString() {
            return "User.UserBuilder(name=" + this.name + ", age=" + this.age + ", bobby=" + this.bobby + ")";
        }
    }
}

请注意,编译后的代码中添加了一些内容,其中包括:

  1. User类中,添加了私有构造函数以及对应的属性赋值操作。
  2. User类中,添加了getter方法和toString()方法的具体实现。
  3. User类中,添加了静态的builder()方法,用于创建UserBuilder对象。
  4. UserBuilder类中,添加了构造函数、链式调用方法以及build()方法的具体实现。

这些额外的代码是Lombok库根据注解自动生成的,它们帮助简化了建造者模式的使用,减少了手动编写重复代码的工作量。这样,您可以更方便地创建和操作User对象。

六、总结

Builder设计模式的优点包括:

  • 可以分步骤构建复杂对象,使构建过程更加灵活和可控。
  • 可以创建不同的表示形式,根据复杂的配置项进行定制化构建,提供了更多对象构建的可能性。
  • 隔离了构建过程和表示,使得扩展和修改更加方便。

然而,Builder设计模式也存在一些缺点:

  • 会增加代码量,因为需要定义和实现多个类。
  • 对于简单对象的构建,使用Builder模式可能会显得过于复杂。

总的来说,Builder设计模式在构建复杂对象时非常有用,并提供了灵活性和可扩展性。但在简单情况下,使用该模式可能会带来一定的开销。

七、和工厂设计模式的区别

建造者设计模式和工厂设计模式是两种常见的创建型设计模式,它们都用于创建对象,但在目的和使用方式上存在一些区别。

  • 工厂设计模式旨在通过一个工厂类来创建对象,隐藏了具体对象的创建细节,并将客户端与具体对象的实例化过程解耦。客户端只需要通过工厂类来请求所需的对象,而不需要直接实例化对象。工厂模式通常适用于创建不同类型对象的场景,通过使用不同的工厂方法或参数,可以创建不同类型的对象。
  • 与之不同,建造者设计模式关注的是逐步构建复杂对象,将对象的构建过程与其表示分离。它允许按照特定的步骤或顺序构建对象,并允许在构建过程中配置对象的各个部分。建造者模式通常适用于创建具有复杂结构或多个可选组件的对象,以及构建过程中涉及多个步骤或变化的对象。

现在,让我们结合生活中的一个例子来说明这两种设计模式的区别。

  1. 假设你要制作一份披萨。使用工厂模式,你可以有一个披萨工厂,通过向工厂提供披萨的类型(例如,奶酪披萨、素食披萨等),工厂将返回相应类型的披萨对象。这种情况下,你只需要告诉工厂你想要的披萨类型,而不需要知道具体如何制作披萨。
  2. 现在,假设你要定制一份复杂的披萨,它有多个可选组件,如酱料、配料和尺寸等。这时,建造者模式更适合。你可以有一个披萨建造者,它提供了设置酱料、配料和尺寸等属性的方法。你可以逐步调用这些方法来构建披萨对象,并在构建过程中根据你的喜好进行定制。

总结一下,工厂设计模式适用于创建不同类型的对象,而建造者设计模式适用于逐步构建复杂对象。工厂模式隐藏了对象的创建细节,而建造者模式允许按照特定的步骤或顺序构建对象,并允许在构建过程中进行配置和定制。

相关推荐
阿伟*rui8 分钟前
配置管理,雪崩问题分析,sentinel的使用
java·spring boot·sentinel
XiaoLeisj2 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
paopaokaka_luck2 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
dayouziei2 小时前
java的类加载机制的学习
java·学习
Yaml44 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~4 小时前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong1616884 小时前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端
aloha_7895 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot
记录成长java5 小时前
ServletContext,Cookie,HttpSession的使用
java·开发语言·servlet
睡觉谁叫~~~5 小时前
一文解秘Rust如何与Java互操作
java·开发语言·后端·rust