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 1/3] =?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; + } + +} From c0d2b8c9e38ea39185c7001a2f7936f2d38aaa03 Mon Sep 17 00:00:00 2001 From: TomXin <766781886@qq.com> Date: Sun, 30 Jan 2022 14:06:43 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=87=8D=E8=BD=BDGeneric?= =?UTF-8?q?Builder=E7=9A=84of=E6=8E=A5=E5=8F=A3=EF=BC=8C=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E6=9C=89=E5=8F=82=E6=9E=84=E9=80=A0(=E6=9C=80=E5=A4=9A5?= =?UTF-8?q?=E4=B8=AA)=E7=9A=84=E8=B0=83=E7=94=A8;=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E9=87=8D=E8=BD=BDwith=E6=8E=A5=E5=8F=A3=EF=BC=8C=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E6=97=A0=E5=8F=82=E6=96=B9=E6=B3=95=E8=B0=83=E7=94=A8?= 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 | 28 +- 2 files changed, 262 insertions(+), 18 deletions(-) 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 index b8da21486..45bde1e3d 100644 --- a/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java +++ b/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java @@ -11,25 +11,32 @@ import java.util.function.Supplier; *

使用方法如下:

*
  * 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();
+ * 		.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();
+ * 		.of(() -> box)
+ * 		.with(Box::setTitle, "Hello Friend!")
+ * 		.with(Box::setLength, 3)
+ * 		.with(Box::setWidth, 4)
+ * 		.with(Box::setHeight, 5)
+ * 		.build();
+ * 
+ *

我们还可以对这样调用有参构造,这对于创建一些在有参构造中包含初始化函数的对象是有意义的

+ *
+ * Box box1 = GenericBuilder
+ * 		.of(Box::new, 2048L, "Hello Partner!", 222, 333, 444)
+ * 		.with(Box::alis)
+ * 		.build();
  * 
* * @author TomXin @@ -43,7 +50,7 @@ public class GenericBuilder implements Builder { private final Supplier instantiator; /** - * 修改器集合 + * 修改器列表 */ private final List> modifiers = new ArrayList<>(); @@ -57,7 +64,7 @@ public class GenericBuilder implements Builder { } /** - * 通过实例化器创建GenericBuilder + * 通过无参数实例化器创建GenericBuilder * * @param instant 实例化器 * @param 目标类型 @@ -67,6 +74,109 @@ public class GenericBuilder implements Builder { return new GenericBuilder<>(instant); } + /** + * 通过1参数实例化器创建GenericBuilder + * + * @param instant 实例化器 + * @param p1 参数一 + * @param 目标类型 + * @param 参数一类型 + * @return GenericBuilder对象 + */ + public static GenericBuilder of(Supplier1 instant, P1 p1) { + Supplier s = () -> instant.get(p1); + return new GenericBuilder<>(s); + } + + /** + * 通过2参数实例化器创建GenericBuilder + * + * @param instant 实例化器 + * @param p1 参数一 + * @param p2 参数二 + * @param 目标类型 + * @param 参数一类型 + * @param 参数二类型 + * @return GenericBuilder对象 + */ + public static GenericBuilder of(Supplier2 instant, P1 p1, P2 p2) { + Supplier s = () -> instant.get(p1, p2); + return new GenericBuilder<>(s); + } + + /** + * 通过3参数实例化器创建GenericBuilder + * + * @param instant 实例化器 + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + * @param 目标类型 + * @param 参数一类型 + * @param 参数二类型 + * @param 参数三类型 + * @return GenericBuilder对象 + */ + public static GenericBuilder of(Supplier3 instant, P1 p1, P2 p2, P3 p3) { + Supplier s = () -> instant.get(p1, p2, p3); + return new GenericBuilder<>(s); + } + + /** + * 通过4参数实例化器创建GenericBuilder + * + * @param instant 实例化器 + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + * @param p4 参数四 + * @param 目标类型 + * @param 参数一类型 + * @param 参数二类型 + * @param 参数三类型 + * @param 参数四类型 + * @return GenericBuilder对象 + */ + public static GenericBuilder of(Supplier4 instant, P1 p1, P2 p2, P3 p3, P4 p4) { + Supplier s = () -> instant.get(p1, p2, p3, p4); + return new GenericBuilder<>(s); + } + + /** + * 通过5参数实例化器创建GenericBuilder + * + * @param instant 实例化器 + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + * @param p4 参数四 + * @param p5 参数五 + * @param 目标类型 + * @param 参数一类型 + * @param 参数二类型 + * @param 参数三类型 + * @param 参数四类型 + * @param 参数五类型 + * @return GenericBuilder对象 + */ + public static GenericBuilder of(Supplier5 instant, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { + Supplier s = () -> instant.get(p1, p2, p3, p4, p5); + return new GenericBuilder<>(s); + } + + + /** + * 调用无参数方法 + * + * @param consumer 无参数Consumer + * @return GenericBuilder对象 + */ + public GenericBuilder with(Consumer consumer) { + modifiers.add(consumer); + return this; + } + + /** * 调用1参数方法 * @@ -170,6 +280,118 @@ public class GenericBuilder implements Builder { return value; } + + /** + * 1参数Supplier + * + * @param 目标类型 + * @param 参数一类型 + */ + @FunctionalInterface + public interface Supplier1 { + /** + * 生成实例的方法 + * + * @param p1 参数一 + * @return 目标对象 + */ + T get(P1 p1); + } + + + /** + * 2参数Supplier + * + * @param 目标类型 + * @param 参数一类型 + * @param 参数二类型 + */ + @FunctionalInterface + public interface Supplier2 { + + /** + * 生成实例的方法 + * + * @param p1 参数一 + * @param p2 参数二 + * @return 目标对象 + */ + T get(P1 p1, P2 p2); + } + + /** + * 3参数Supplier + * + * @param 目标类型 + * @param 参数一类型 + * @param 参数二类型 + * @param 参数三类型 + */ + @FunctionalInterface + public interface Supplier3 { + + /** + * 生成实例的方法 + * + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + * @return 目标对象 + */ + T get(P1 p1, P2 p2, P3 p3); + } + + + /** + * 4参数Supplier + * + * @param 目标类型 + * @param 参数一类型 + * @param 参数二类型 + * @param 参数三类型 + * @param 参数四类型 + */ + @FunctionalInterface + public interface Supplier4 { + + /** + * 生成实例的方法 + * + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + * @param p4 参数四 + * @return 目标对象 + */ + T get(P1 p1, P2 p2, P3 p3, P4 p4); + } + + /** + * 5参数Supplier + * + * @param 目标类型 + * @param 参数一类型 + * @param 参数二类型 + * @param 参数三类型 + * @param 参数四类型 + * @param 参数五类型 + */ + @FunctionalInterface + public interface Supplier5 { + + /** + * 生成实例的方法 + * + * @param p1 参数一 + * @param p2 参数二 + * @param p3 参数三 + * @param p4 参数四 + * @param p5 参数五 + * @return 目标对象 + */ + T get(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5); + } + /** * 1参数Consumer */ 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 index 0ac1cd728..b3753e62d 100644 --- a/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/builder/GenericBuilderTest.java @@ -1,8 +1,7 @@ package cn.hutool.core.builder; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; +import cn.hutool.core.util.StrUtil; +import lombok.*; import org.junit.Test; /** @@ -31,6 +30,11 @@ public class GenericBuilderTest { .with(Box::setHeight, 5) .build(); System.out.println(boxModified); + Box box1 = GenericBuilder + .of(Box::new, 2048L, "Hello Partner!", 222, 333, 444) + .with(Box::alis) + .build(); + System.out.println(box1); } @Getter @@ -42,6 +46,24 @@ public class GenericBuilderTest { private Integer length; private Integer width; private Integer height; + private String titleAlias; + + public Box() { + } + + public Box(Long id, String title, Integer length, Integer width, Integer height) { + this.id = id; + this.title = title; + this.length = length; + this.width = width; + this.height = height; + } + + public void alis() { + if (StrUtil.isNotBlank(this.title)) { + this.titleAlias = "TomXin:\"" + title + "\""; + } + } } } From 7096ef04e01f5af15e959cab41fc7fb0de74f5f6 Mon Sep 17 00:00:00 2001 From: TomXin <766781886@qq.com> Date: Wed, 2 Feb 2022 11:55:47 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E8=A1=A5=E5=85=85=E5=85=B3=E4=BA=8EGeneric?= =?UTF-8?q?Builder=E7=B1=BB=E7=9A=84=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/cn/hutool/core/builder/GenericBuilder.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 index 45bde1e3d..3046427bd 100644 --- a/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java +++ b/hutool-core/src/main/java/cn/hutool/core/builder/GenericBuilder.java @@ -31,13 +31,17 @@ import java.util.function.Supplier; * .with(Box::setHeight, 5) * .build(); * - *

我们还可以对这样调用有参构造,这对于创建一些在有参构造中包含初始化函数的对象是有意义的

+ *

我们还可以对这样调用有参构造,这对于创建一些在有参构造中包含初始化函数的对象是有意义的:

*
  * Box box1 = GenericBuilder
  * 		.of(Box::new, 2048L, "Hello Partner!", 222, 333, 444)
  * 		.with(Box::alis)
  * 		.build();
  * 
+ *

注意:本工具类支持调用的方法的参数数量不超过5个,更多的参数不利于阅读和维护。 + * 关于Java方法的参数个数限制似乎并没有明确统一的规范,网络上众说纷纭,这里取个相对平均的数5。 + * 特殊需要求可以基于此类进行拓展. + *

* * @author TomXin * @since jdk1.8