Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/security/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
这是在真实软件环境中创建生成器模式的正确方法吗?简而言之,用java创建生成器模式的最佳方法是什么_Java_Builder Pattern - Fatal编程技术网

这是在真实软件环境中创建生成器模式的正确方法吗?简而言之,用java创建生成器模式的最佳方法是什么

这是在真实软件环境中创建生成器模式的正确方法吗?简而言之,用java创建生成器模式的最佳方法是什么,java,builder-pattern,Java,Builder Pattern,这是在java中创建生成器模式的正确方法吗?如果不是,可能会有什么变化 尝试使用静态类 公共类多元宇宙{ 私立UUID大学; 私有字符串universeName; 私有字符串universitype; 私人存在; 人类存在的公共布尔{ 回归人的存在; } 私有多元宇宙{ 抛出新的IllegalStateException无法从构造函数创建对象:尝试使用生成器; } 私有MultiverseUID universeId、字符串universeName、字符串universeType、布尔型huma

这是在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无法从构造函数创建对象:尝试使用生成器; }
预期和实际是相同的。但不确定这是实现目标的最佳方式。请纠正或建议我这一点,[需要专家建议]

关于您的方法的一些注意事项:

我认为通过反射“阻止”用户创建实例没有任何意义。因为您定义了一个构造函数,所以无论如何都没有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风格前缀符号。这是编译器不支持类型检查时代的遗迹。大多数人喜欢读单词。