一、什么是建造者模式
建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。
以下是建造者模式的一般流程
-
定义产品类:首先,需要定义一个产品类,它是由多个部分组成的复杂对象。产品类通常具有多个属性和方法。
-
创建建造者类:建造者类负责实际构建产品对象。它提供了一系列方法来设置产品的不同属性。
-
设置产品属性方法:建造者类中的方法用于设置产品的属性。每个方法通常设置一个特定的属性,并返回建造者对象本身,以便支持方法链式调用。
-
构建产品方法:当所有属性设置完毕后,建造者类提供一个构建产品的方法。该方法执行实际的构建过程,将属性组装成最终的产品对象。
-
创建指导者类(可选):在某些情况下,可以创建一个指导者类来协调建造者的构建过程。指导者类知道构建的顺序和方式,并且负责按照正确的顺序调用建造者的方法。
-
客户端使用:客户端代码通过实例化建造者对象,并使用建造者对象的方法来设置产品的属性。最后,通过调用建造者对象的构建产品方法,获取构建完成的产品对象。
二、建造者模式都可以干什么
意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
主要解决:主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。
何时使用:一些基本部件不会变,而其组合经常变化的时候。
如何解决:将变与不变分离开。
关键代码:建造者:创建和提供实例,导演:管理建造出来的实例的依赖关系。
应用实例: 1、去肯德基,汉堡、可乐、薯条、炸鸡翅等是不变的,而其组合是经常变化的,生成出所谓的"套餐"。 2、JAVA 中的 StringBuilder。
三、建造者模式的优缺点
优点:
-
分离构建过程和表示,使得构建过程更加灵活,可以构建不同的表示。
-
可以更好地控制构建过程,隐藏具体构建细节。
-
代码复用性高,可以在不同的构建过程中重复使用相同的建造者。
缺点:
-
如果产品的属性较少,建造者模式可能会导致代码冗余。
-
建造者模式增加了系统的类和对象数量。
四、建造者模式的使用场景:
1、需要生成的对象具有复杂的内部结构。
2、需要生成的对象内部属性本身相互依赖。
建造者模式在创建复杂对象时非常有用,特别是当对象的构建过程涉及多个步骤或参数时。它可以提供更好的灵活性和可维护性,同时使得代码更加清晰可读。
==注意事项==:与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。
五、一个牛逼的封装,基于JDK8封装的通用建造者
封装类
java
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<T> {
private final Supplier<T> instantiator;
private final List<Consumer<T>> instantiatorModifiers = new ArrayList<>();
private final List<Consumer<T>> keyValueModifiers = new ArrayList<>();
public GenericBuilder(Supplier<T> instantiator) {
this.instantiator = instantiator;
}
public static <T> GenericBuilder<T> of(Supplier<T> instantiator) {
return new GenericBuilder<>(instantiator);
}
public <U> GenericBuilder<T> with(BiConsumer<T, U> consumer, U value) {
Consumer<T> c = instance -> consumer.accept(instance, value);
instantiatorModifiers.add(c);
return this;
}
public <K, V> GenericBuilder<T> with(KeyValueConsumer<T, K, V> consumer, K key, V value) {
Consumer<T> 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());
}
}
使用方法
java
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());
}