From 9d5c2ffc1a9037efe0a9e46f06feff0554ed87e6 Mon Sep 17 00:00:00 2001
From: TomXin <766781886@qq.com>
Date: Sat, 29 Jan 2022 17:34:52 +0800
Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9EGenericBuilder?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../hutool/core/builder/GenericBuilder.java | 252 ++++++++++++++++++
.../core/builder/GenericBuilderTest.java | 47 ++++
2 files changed, 299 insertions(+)
create mode 100644 hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java
create mode 100644 hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java
diff --git a/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java b/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java
new file mode 100644
index 000000000..b8da21486
--- /dev/null
+++ b/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java
@@ -0,0 +1,252 @@
+package cn.hutool.core.builder;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+/**
+ *
通用Builder
+ * 参考: 一看就会的java8通用Builder
+ * 使用方法如下:
+ *
+ * Box box = GenericBuilder
+ * .of(Box::new)
+ * .with(Box::setId, 1024L)
+ * .with(Box::setTitle, "Hello World!")
+ * .with(Box::setLength, 9)
+ * .with(Box::setWidth, 8)
+ * .with(Box::setHeight, 7)
+ * .build();
+ *
+ *
+ *
+ * 我们也可以对已创建的对象进行修改:
+ *
+ * Box boxModified = GenericBuilder
+ * .of(() -> box)
+ * .with(Box::setTitle, "Hello Friend!")
+ * .with(Box::setLength, 3)
+ * .with(Box::setWidth, 4)
+ * .with(Box::setHeight, 5)
+ * .build();
+ *
+ *
+ * @author TomXin
+ * @since jdk1.8
+ */
+public class GenericBuilder implements Builder {
+
+ /**
+ * 实例化器
+ */
+ private final Supplier instantiator;
+
+ /**
+ * 修改器集合
+ */
+ private final List> modifiers = new ArrayList<>();
+
+ /**
+ * 构造
+ *
+ * @param instant 实例化器
+ */
+ public GenericBuilder(Supplier instant) {
+ this.instantiator = instant;
+ }
+
+ /**
+ * 通过实例化器创建GenericBuilder
+ *
+ * @param instant 实例化器
+ * @param 目标类型
+ * @return GenericBuilder对象
+ */
+ public static GenericBuilder of(Supplier instant) {
+ return new GenericBuilder<>(instant);
+ }
+
+ /**
+ * 调用1参数方法
+ *
+ * @param consumer 1参数Consumer
+ * @param p1 参数一
+ * @param 参数一类型
+ * @return GenericBuilder对象
+ */
+ public GenericBuilder with(Consumer1 consumer, P1 p1) {
+ Consumer c = instance -> consumer.accept(instance, p1);
+ modifiers.add(c);
+ return this;
+ }
+
+ /**
+ * 调用2参数方法
+ *
+ * @param consumer 2参数Consumer
+ * @param p1 参数一
+ * @param p2 参数二
+ * @param 参数一类型
+ * @param 参数二类型
+ * @return GenericBuilder对象
+ */
+ public GenericBuilder with(Consumer2 consumer, P1 p1, P2 p2) {
+ Consumer c = instance -> consumer.accept(instance, p1, p2);
+ modifiers.add(c);
+ return this;
+ }
+
+ /**
+ * 调用3参数方法
+ *
+ * @param consumer 3参数Consumer
+ * @param p1 参数一
+ * @param p2 参数二
+ * @param p3 参数三
+ * @param 参数一类型
+ * @param 参数二类型
+ * @param 参数三类型
+ * @return GenericBuilder对象
+ */
+ public GenericBuilder with(Consumer3 consumer, P1 p1, P2 p2, P3 p3) {
+ Consumer c = instance -> consumer.accept(instance, p1, p2, p3);
+ modifiers.add(c);
+ return this;
+ }
+
+ /**
+ * 调用4参数方法
+ *
+ * @param consumer 4参数Consumer
+ * @param p1 参数一
+ * @param p2 参数二
+ * @param p3 参数三
+ * @param p4 参数四
+ * @param 参数一类型
+ * @param 参数二类型
+ * @param 参数三类型
+ * @param 参数四类型
+ * @return GenericBuilder对象
+ */
+ public GenericBuilder with(Consumer4 consumer, P1 p1, P2 p2, P3 p3, P4 p4) {
+ Consumer c = instance -> consumer.accept(instance, p1, p2, p3, p4);
+ modifiers.add(c);
+ return this;
+ }
+
+ /**
+ * 调用5参数方法
+ *
+ * @param consumer 5参数Consumer
+ * @param p1 参数一
+ * @param p2 参数二
+ * @param p3 参数三
+ * @param p4 参数四
+ * @param p5 参数五
+ * @param 参数一类型
+ * @param 参数二类型
+ * @param 参数三类型
+ * @param 参数四类型
+ * @param 参数五类型
+ * @return GenericBuilder对象
+ */
+ public GenericBuilder with(Consumer5 consumer, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {
+ Consumer c = instance -> consumer.accept(instance, p1, p2, p3, p4, p5);
+ modifiers.add(c);
+ return this;
+ }
+
+ /**
+ * 构建
+ *
+ * @return 目标对象
+ */
+ @Override
+ public T build() {
+ T value = instantiator.get();
+ modifiers.forEach(modifier -> modifier.accept(value));
+ modifiers.clear();
+ return value;
+ }
+
+ /**
+ * 1参数Consumer
+ */
+ @FunctionalInterface
+ public interface Consumer1 {
+ /**
+ * 接收参数方法
+ *
+ * @param t 对象
+ * @param p1 参数二
+ */
+ void accept(T t, P1 p1);
+ }
+
+ /**
+ * 2参数Consumer
+ */
+ @FunctionalInterface
+ public interface Consumer2 {
+ /**
+ * 接收参数方法
+ *
+ * @param t 对象
+ * @param p1 参数一
+ * @param p2 参数二
+ */
+ void accept(T t, P1 p1, P2 p2);
+ }
+
+ /**
+ * 3参数Consumer
+ */
+ @FunctionalInterface
+ public interface Consumer3 {
+ /**
+ * 接收参数方法
+ *
+ * @param t 对象
+ * @param p1 参数一
+ * @param p2 参数二
+ * @param p3 参数三
+ */
+ void accept(T t, P1 p1, P2 p2, P3 p3);
+ }
+
+ /**
+ * 4参数Consumer
+ */
+ @FunctionalInterface
+ public interface Consumer4 {
+ /**
+ * 接收参数方法
+ *
+ * @param t 对象
+ * @param p1 参数一
+ * @param p2 参数二
+ * @param p3 参数三
+ * @param p4 参数四
+ */
+ void accept(T t, P1 p1, P2 p2, P3 p3, P4 p4);
+ }
+
+ /**
+ * 5参数Consumer
+ */
+ @FunctionalInterface
+ public interface Consumer5 {
+ /**
+ * 接收参数方法
+ *
+ * @param t 对象
+ * @param p1 参数一
+ * @param p2 参数二
+ * @param p3 参数三
+ * @param p4 参数四
+ * @param p5 参数五
+ */
+ void accept(T t, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5);
+ }
+}
diff --git a/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java b/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java
new file mode 100644
index 000000000..0ac1cd728
--- /dev/null
+++ b/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java
@@ -0,0 +1,47 @@
+package cn.hutool.core.builder;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.junit.Test;
+
+/**
+ * {@link GenericBuilder} 单元测试类
+ *
+ * @author TomXin
+ */
+public class GenericBuilderTest {
+
+ @Test
+ public void test() {
+ Box box = GenericBuilder
+ .of(Box::new)
+ .with(Box::setId, 1024L)
+ .with(Box::setTitle, "Hello World!")
+ .with(Box::setLength, 9)
+ .with(Box::setWidth, 8)
+ .with(Box::setHeight, 7)
+ .build();
+ System.out.println(box);
+ Box boxModified = GenericBuilder
+ .of(() -> box)
+ .with(Box::setTitle, "Hello Friend!")
+ .with(Box::setLength, 3)
+ .with(Box::setWidth, 4)
+ .with(Box::setHeight, 5)
+ .build();
+ System.out.println(boxModified);
+ }
+
+ @Getter
+ @Setter
+ @ToString
+ public static class Box {
+ private Long id;
+ private String title;
+ private Integer length;
+ private Integer width;
+ private Integer height;
+ }
+
+}