这是在真实软件环境中创建生成器模式的正确方法吗?简而言之,用java创建生成器模式的最佳方法是什么
这是在java中创建生成器模式的正确方法吗?如果不是,可能会有什么变化 尝试使用静态类 公共类多元宇宙{ 私立UUID大学; 私有字符串universeName; 私有字符串universitype; 私人存在; 人类存在的公共布尔{ 回归人的存在; } 私有多元宇宙{ 抛出新的IllegalStateException无法从构造函数创建对象:尝试使用生成器; } 私有MultiverseUID universeId、字符串universeName、字符串universeType、布尔型humanExistence{ 超级的 这是。世界开斋节=世界开斋节; this.universeName=universeName; this.universeType=universeType; 人的存在=人的存在; } 公共静态类MultiverseBuilder{ 私立UUID大学; 私有字符串universeName; 私有字符串universitype; 私人存在; 公共MultiverseBuilder MakeUUID uuid uuid{ 这个。universeId=uuid; 归还这个; } 公共综合性大学{ 这个。universeName=大学; 归还这个; } public MultiverseBuilder SetUniversityPerstring UniversityType{ this.universitype=universitype; 归还这个; } 公共多元文化构建者非人类存在{ 人的存在=人的存在; 归还这个; } 公共多元宇宙构建{ 回归新的多元宇宙,宇宙,宇宙,人类存在; } } 公共大学开斋节{ 回归种族隔离; } 公共字符串getUniverseName{ 返回universeName; } 公共字符串GetUniversityType{ 返回UniversityPE; } } Junit5测试 公共类断言Test6{ 专用静态记录器Logger=Logger.getLoggerAssertionsTest6.class.getName; 多元宇宙; @之前 无效初始{ 多元宇宙=新多元宇宙 .makeUUIdUUID.randomUUID .createUniverseEarth .宇宙大爆炸 .非人的存在 建筑 } @试验 @DisplayNameBuilder测试 无效测试生成器{ AsserteQualsBigBang,multiverse.GetUniversityPE,测试失败; logger.infoBuilder测试; } } 阻止反射通过这样做直接从多重宇宙类生成对象 私有多元宇宙{ 抛出新的IllegalStateException无法从构造函数创建对象:尝试使用生成器; }这是在真实软件环境中创建生成器模式的正确方法吗?简而言之,用java创建生成器模式的最佳方法是什么,java,builder-pattern,Java,Builder Pattern,这是在java中创建生成器模式的正确方法吗?如果不是,可能会有什么变化 尝试使用静态类 公共类多元宇宙{ 私立UUID大学; 私有字符串universeName; 私有字符串universitype; 私人存在; 人类存在的公共布尔{ 回归人的存在; } 私有多元宇宙{ 抛出新的IllegalStateException无法从构造函数创建对象:尝试使用生成器; } 私有MultiverseUID universeId、字符串universeName、字符串universeType、布尔型huma
预期和实际是相同的。但不确定这是实现目标的最佳方式。请纠正或建议我这一点,[需要专家建议]关于您的方法的一些注意事项: 我认为通过反射“阻止”用户创建实例没有任何意义。因为您定义了一个构造函数,所以无论如何都没有arg构造函数。因此,只能通过传递生成器来创建实例。 我喜欢将生成器实例传递给构造函数。这样,即使类有很多字段,您也将拥有可读的代码。 我喜欢称我的建筑商为建筑商。这是一个嵌套类,您可能会一直编写Multiverse.Builder。 我喜欢实际的类为构建器提供工厂方法,这样我就可以编写Multiverse.builder并开始填充字段。 生成器类的方法应具有一致的命名方案。 这就是我的构建者通常的样子:
public class Multiverse {
private final UUID universeId;
private final String universeName;
private final String universeType;
private final Boolean humanExistence;
private Multiverse(Builder builder) {
this.universeId = builder.universeId;
this.universeName = builder.universeName;
this.universeType = builder.universeType;
this.humanExistence = builder.humanExistence;
}
public static Builder builder() {
return new Builder();
}
public UUID getUniverseId() {
return universeId;
}
public String getUniverseName() {
return universeName;
}
public String getUniverseType() {
return universeType;
}
public Boolean getHumanExistence() {
return humanExistence;
}
public Builder toBuilder() {
return new Builder(this);
}
public static class Builder {
private UUID universeId;
private String universeName;
private String universeType;
private Boolean humanExistence;
private Builder() {}
private Builder(Multiverse multiverse) {
this.universeId = multiverse.universeId;
this.universeName = multiverse.universeName;
this.universeType = multiverse.universeType;
this.humanExistence = multiverse.humanExistence;
}
public Builder withUniverseId(UUID universeId) {
this.universeId = universeId;
return this;
}
public Builder withUniverseName(String universeName) {
this.universeName = universeName;
return this;
}
public Builder withUniverseType(String universeType) {
this.universeType = universeType;
return this;
}
public Builder withHumanExistence(Boolean humanExistence) {
this.humanExistence = humanExistence;
return this;
}
public Multiverse build() {
return new Multiverse(this);
}
}
}
创建多重宇宙的工作原理如下:
Multiverse multiverse1 = Multiverse.builder()
.withUniverseId(UUID.fromString("550e8400-e29b-11d4-a716-446655440000"))
.withUniverseName("my first multiverse")
.withUniverseType("type a")
.withHumanExistence(true)
.build();
Multiverse multiverse2 = multiverse1.toBuilder()
.withUniverseId(UUID.fromString("759e947a-7492-af67-87bd-87de9e7f5e95"))
.withUniverseName("my second multiverse")
.build();
如果您决定稍后编辑此多元宇宙,您可以这样做:
Multiverse multiverse1 = Multiverse.builder()
.withUniverseId(UUID.fromString("550e8400-e29b-11d4-a716-446655440000"))
.withUniverseName("my first multiverse")
.withUniverseType("type a")
.withHumanExistence(true)
.build();
Multiverse multiverse2 = multiverse1.toBuilder()
.withUniverseId(UUID.fromString("759e947a-7492-af67-87bd-87de9e7f5e95"))
.withUniverseName("my second multiverse")
.build();
这将实现以下断言:
assert multiverse1.getUniverseId().equals("550e8400-e29b-11d4-a716-446655440000");
assert multiverse1.getUniverseName().equals("my first multiverse");
assert multiverse1.getUniverseType.equals("type a");
assert multiverse1.getHumanExistence == true;
assert multiverse2.getUniverseId().equals("759e947a-7492-af67-87bd-87de9e7f5e95");
assert multiverse2.getUniverseName().equals("my second multiverse");
assert multiverse2.getUniverseType.equals("type a");
assert multiverse2.getHumanExistence == true;
设计注意事项:
强制使用生成器不允许直接创建实例?
不变性创建实例后在生成器上调用setter时会发生什么?
可重用性:是否允许生成器创建多个实例?
不可重用构建器示例,可用于创建一个实例,该实例实际上是不可变的:
我想这是最后的解决办法了,谢谢你
公共最终类引导服务器{//步骤1使类和字段为最终类
private final Integer port;
private final String serverName;
private final String serverType;
private final String listenerType;
private BootServer(Builder builder) {// step #2 create private constructor
this.port = builder.port;
this.serverName = builder.serverName;
this.serverType = builder.serverType;
this.listenerType=builder.listenerType;
}
public static Builder builder() {//Step#3 create static builder method to return Builder
return new Builder();
}
public static final class Builder {//Step#4 create public static builder class
private Integer port;
private String serverName;
private String serverType;
private String listenerType;
private Builder(){
}
public BootServer build() {//Step#5 create build method to return BootServer Object with this object
return new BootServer(this);
}
public Builder addServerPort(Integer port) {//Step#6 finally create all build method to set values to main class
this.port=port;
return this;
}
public Builder addServerName(String name) {
this.serverName=name;
return this;
}
public Builder setServerType(String serverType) {
this.serverType=serverType;
return this;
}
public Builder setListenerType(String listenerType) {
this.listenerType=listenerType;
return this;
}
}
@Override
public String toString() {
return "BootServer [port=" + port + ", serverName=" + serverName + ", serverType=" + serverType
+ ", listenerType=" + listenerType + "]";
}
}这不是建筑商通常的样子。在您的示例中,为什么要向产品类Multiverse添加循环依赖项?通常,构建器通过setter收集数据并存储这些值。然后在调用Build时构造产品的一个实例。在您的案例中,构建者是使用他应该创建的产品构建的,并且产品是构建的
从应该创建它的生成器中删除。通常,您会调用nwe生成器。然后是builder.setUniversalEnestring,最后通过调用builder.Build获得产品。这是通常的做法。对不起,我听不懂。可以使用静态生成器方法创建空生成器。如果您想创建最后一个类,可以调用buildon。这给了你一个多元宇宙的永恒实例。如果您想在以后对其进行修改,可以通过调用toBuilder从该实例创建一个新的构建器。没有循环依赖关系。我从来没有读过问题中的immutable。也许是我错过了,或者是你编的。构建器不需要返回不可变的产品。这是个特例。他只询问了遵循构建器模式的正确方法,提出了一些具有嵌套类的奇特版本。我理解这一点,就好像他想要的是标准的生成器模式,而不是特例。您的版本不是标准版本。这就是我的观点。但你是对的。这是关于你的建设者是一个不变的产品,它将工作。我必须道歉。但是,这种依赖关系是循环的,因为这两种类型相互依赖。您可以通过将构建器移动到不同的包(例如helpers)来证明这一点,或者在您的情况下,只需查看构造函数即可。当然,但它是一种原子单元。如果没有它应该构建的产品,构建器就不能存在。在这种情况下,创建多元宇宙的唯一方法是通过构建器。因此,删除构建器将毫无意义。然而,这个问题太广泛了,我认为没有正确的答案。我刚才给了一个生成不可变实例的构建器的固执己见的例子。“a”是什么意思?或者我应该选择调用bMultiverse方法吗?我不知道,因为我不知道“b”是什么意思。为什么不叫它immutableMultiverseBuilder呢?现在我想知道是什么让这个方法与可变多维构建器相比如此特殊。命名约定是一件好事,也是一个有价值的建议,但是应该避免使用这种类似于匈牙利语的C风格前缀符号。这是编译器不支持类型检查时代的遗迹。大多数人喜欢读单词。