【设计模式系列】建造者模式

这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战

前言

建造者设计模式和工厂模式,抽象工厂模式一样也是创建型设计模式之一。

如果在需要创建一个对象时,该对象包含大量的参数,使用工厂模式或抽象工厂模式会存在一些问题。为了解决这些问题,可以使用建造者模式。

工厂模式和抽象工厂模式在这种情况下主要存在下列问题:

  • 有太多参数需要从客户端传递给工厂类,这很容易出错,尤其是当有很多数据类型一样的参数时,很难正确维护参数的顺序;
  • 如果有参数是可选的,则需要在参数列表中传递NULL值;
  • 如果对象很重,创建起来很复杂,那么这些复杂性都会侵入到工厂类中;
  • 这种问题虽然可以通过提供一个包含所有必须参数的构造方法,然后其他可选参数使用setter方法来设置,但是这样容易造成对象状态的不一致。

为了解决这一系列问题,在建造者模式中,通过提供一种逐步构建对象的方法,并将最终对象返回,可以解决大量参数和对象状态不一致的问题。

建造者模式结构

如果实现建造者设计模式,主要分以下步骤:

  • 首先创建一个静态内部类,将所有需要构建对象的属性赋值到内部类中;按照约定的命名规范,一般命名为XXXBuilder,比如需要创建一个Computer对象,则静态内部类为ComputerBuilder;
  • 这个Builder类需要提供一个包含所有参数的构造方法;
  • 然后Builder类还需要提供设置可选参数的方法,该设置方法需要将Builder对象返回;
  • 最后需要在Builder类中提供build()方法,该方法将返回客户端最终需要的对象,也就是Computer对象。

代码结构如下:

package com.heiz.design.builder;

/**
 * @author 小黑说Java
 * @ClassName Computer
 * @Description
 * @date 2021/11/20
 **/

public class Computer {

    //必选参数
    /**
     * 硬盘
     */
    private String HDD;
    /**
     * 内存
     */
    private String RAM;

    // 可选参数
    /**
     * 显卡
     */
    private boolean isGraphicsCardEnabled;
    /**
     * 蓝牙
     */
    private boolean isBluetoothEnabled;


    public String getHDD() {
        return HDD;
    }

    public String getRAM() {
        return RAM;
    }

    public boolean isGraphicsCardEnabled() {
        return isGraphicsCardEnabled;
    }

    public boolean isBluetoothEnabled() {
        return isBluetoothEnabled;
    }

    private Computer(ComputerBuilder builder) {
        this.HDD = builder.HDD;
        this.RAM = builder.RAM;
        this.isGraphicsCardEnabled = builder.isGraphicsCardEnabled;
        this.isBluetoothEnabled = builder.isBluetoothEnabled;
    }

    //Builder Class
    public static class ComputerBuilder {

        //必选参数
        /**
         * 硬盘
         */
        private String HDD;
        /**
         * 内存
         */
        private String RAM;

        // 可选参数
        /**
         * 显卡
         */
        private boolean isGraphicsCardEnabled;
        /**
         * 蓝牙
         */
        private boolean isBluetoothEnabled;

        public ComputerBuilder(String hdd, String ram) {
            this.HDD = hdd;
            this.RAM = ram;
        }

        public ComputerBuilder setGraphicsCardEnabled(boolean isGraphicsCardEnabled) {
            this.isGraphicsCardEnabled = isGraphicsCardEnabled;
            return this;
        }

        public ComputerBuilder setBluetoothEnabled(boolean isBluetoothEnabled) {
            this.isBluetoothEnabled = isBluetoothEnabled;
            return this;
        }

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

复制代码

需要注意,Computer类只有getter方法,没有公共构造函数。因此,获得Computer对象的唯一方法是通过ComputerBuilder类。

然后我们使用一个简单的测试,来测一下我们的代码:

package com.heiz.design.builder;

/**
 * @author 小黑说Java
 * @ClassName BuilderTest
 * @Description
 * @date 2021/11/20
 **/
public class BuilderTest {
    public static void main(String[] args) {
        Computer computer = new Computer.ComputerBuilder("500GB", "2 GB")
                .setBluetoothEnabled(false)
                .setGraphicsCardEnabled(true)
                .build();
    }
}
复制代码

建造者模式的优点

使用建造者模式将创建对象的可变属性和不可变属性进行分离,对于客户端只能使用建造者创建对象,不用关心创建细节,所以建造者模式更易于扩展,便于控制细节风险。

JDK中的建造者模式

在JDK中最典型的建造者模式就是我们常用的StringBuilder和StringBuffer:

  • java.lang.StringBuilder#append() 线程不安全
  • java.lang.StringBuffer#append() 线程安全

以上就是本期建造者模式的全部内容,如果对你有所帮助,点个赞是对我最大的鼓励。

おすすめ

転載: juejin.im/post/7032549117796712456
おすすめ