详解建造者模式,带一个优雅的封装(jdk8通用)

2023年 9月 16日 23.1k 0

一、什么是建造者模式

建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。

以下是建造者模式的一般流程

  • 定义产品类:首先,需要定义一个产品类,它是由多个部分组成的复杂对象。产品类通常具有多个属性和方法。

  • 创建建造者类:建造者类负责实际构建产品对象。它提供了一系列方法来设置产品的不同属性。

  • 设置产品属性方法:建造者类中的方法用于设置产品的属性。每个方法通常设置一个特定的属性,并返回建造者对象本身,以便支持方法链式调用。

  • 构建产品方法:当所有属性设置完毕后,建造者类提供一个构建产品的方法。该方法执行实际的构建过程,将属性组装成最终的产品对象。

  • 创建指导者类(可选):在某些情况下,可以创建一个指导者类来协调建造者的构建过程。指导者类知道构建的顺序和方式,并且负责按照正确的顺序调用建造者的方法。

  • 客户端使用:客户端代码通过实例化建造者对象,并使用建造者对象的方法来设置产品的属性。最后,通过调用建造者对象的构建产品方法,获取构建完成的产品对象。

sequenceDiagram
    participant 客户端
    participant 建造者
    participant 产品

    客户端->建造者: 实例化建造者对象
    客户端->建造者: 调用建造者对象的设置属性方法1
    建造者-->产品: 设置属性1
    客户端->建造者: 调用建造者对象的设置属性方法2
    建造者-->产品: 设置属性2
    客户端->建造者: 调用建造者对象的设置属性方法3
    建造者-->产品: 设置属性3
    客户端->建造者: 调用建造者对象的构建产品方法
    建造者-->产品: 构建产品
    建造者-->客户端: 返回构建完成的产品对象
    客户端->产品: 使用产品对象

二、建造者模式都可以干什么

意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。

主要解决:主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。

何时使用:一些基本部件不会变,而其组合经常变化的时候。

如何解决:将变与不变分离开。

关键代码:建造者:创建和提供实例,导演:管理建造出来的实例的依赖关系。

应用实例: 1、去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出所谓的"套餐"。 2、JAVA 中的 StringBuilder。

三、建造者模式的优缺点

优点:

  • 分离构建过程和表示,使得构建过程更加灵活,可以构建不同的表示。

  • 可以更好地控制构建过程,隐藏具体构建细节。

  • 代码复用性高,可以在不同的构建过程中重复使用相同的建造者。

缺点:

  • 如果产品的属性较少,建造者模式可能会导致代码冗余。

  • 建造者模式增加了系统的类和对象数量。

四、建造者模式的使用场景:

1、需要生成的对象具有复杂的内部结构。

2、需要生成的对象内部属性本身相互依赖。

建造者模式在创建复杂对象时非常有用,特别是当对象的构建过程涉及多个步骤或参数时。它可以提供更好的灵活性和可维护性,同时使得代码更加清晰可读。

==注意事项==:与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。

五、一个牛逼的封装,基于JDK8封装的通用建造者

封装类

import com.hytto.gfw.common.OptionResult;

import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * 通用Builder
 */
public class GenericBuilder {

    private final Supplier instantiator;
    private final List instantiatorModifiers = new ArrayList();
    private final List keyValueModifiers = new ArrayList();

    public GenericBuilder(Supplier instantiator) {
        this.instantiator = instantiator;
    }

    public static  GenericBuilder of(Supplier instantiator) {
        return new GenericBuilder(instantiator);
    }

    public  GenericBuilder with(BiConsumer consumer, U value) {
        Consumer c = instance -> consumer.accept(instance, value);
        instantiatorModifiers.add(c);
        return this;
    }

    public  GenericBuilder with(KeyValueConsumer consumer, K key, V value) {
        Consumer c = instance -> consumer.accept(instance, key, value);
        keyValueModifiers.add(c);
        return this;
    }

    public T build() {
        T value = instantiator.get();
        instantiatorModifiers.forEach(modifier -> modifier.accept(value));
        keyValueModifiers.forEach(keyValueModifier -> keyValueModifier.accept(value));
        instantiatorModifiers.clear();
        keyValueModifiers.clear();
        return value;
    }

    public static void main(String[] args) {
        OptionResult optionResult = GenericBuilder.of(OptionResult::new)
                .with(OptionResult::setTip, "好了呢")
                .with(OptionResult::setSuccess, true)
                .build();
        System.out.println(optionResult.toString());
    }

}

使用方法

public static void main(String[] args) {
    OptionResult optionResult = GenericBuilder.of(OptionResult::new)
            .with(OptionResult::setTip, "好了呢")
            .with(OptionResult::setSuccess, true)
            .build();
    System.out.println(optionResult.toString());
}

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论