Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.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_Design Patterns_Builder - Fatal编程技术网

Java 具有条件包含元素的生成器

Java 具有条件包含元素的生成器,java,design-patterns,builder,Java,Design Patterns,Builder,我一直在想,是否可以更优雅地使用可选参数创建生成器: 我拥有的:带有名称、id、年龄的对象 我有复杂的条件,包括年龄,我想把它发送给建设者成功的条件,但我想有一个优雅的一行一个参数 到目前为止,我所拥有的: Builder.name("name").id("id").age(age, complexCondition).build(); 或 还有更好的选择吗?我想解决的条件,我有它没有过度工程建设者和没有过度编码的每一个复杂的条件检查 upd:我正在寻找的解决方案没有: a) 将复杂的检查或

我一直在想,是否可以更优雅地使用可选参数创建生成器:

我拥有的:带有名称、id、年龄的对象

我有复杂的条件,包括年龄,我想把它发送给建设者成功的条件,但我想有一个优雅的一行一个参数

到目前为止,我所拥有的:

 Builder.name("name").id("id").age(age, complexCondition).build();

还有更好的选择吗?我想解决的条件,我有它没有过度工程建设者和没有过度编码的每一个复杂的条件检查


upd:我正在寻找的解决方案没有:

a) 将复杂的检查或布尔值传递给构建者——根据定义,这不是他的工作


b) 在调用builder的方法中,不必为每个条件添加3行check,那么,如果您希望每个方法调用一个参数,您可以拆分

Builder.name("name").id("id").age(age, complexCondition).build();
进入

你可能想考虑制作<代码>复杂条件 A<代码>谓词< /代码>(其中<代码>某物< /代码>是用于评估条件的某种类型的实例)。这样,当您调用

Builder
build()
时,只有在提供了年龄参数的情况下才能计算复杂条件

build
方法可以如下所示:

public SomeClass build() {
    SomeClass obj = new SomeClass();
    obj.setName(name);
    if (age != null && someCondition != null && someCondition.test(something)) {
        obj.setAge(age);
    }
    return obj;
}
Builder builder = Builder
    .name("name")
    .id("id")
    .age(complexCondition ? age : null);
public Builder age(Integer age) {
    if (age != null) {
        this.age = age;
    }
    return this;
}
我不确定什么是
东西。这取决于你复杂情况的性质

或者,如果您希望条件是可选的:

public SomeClass build() {
    SomeClass obj = new SomeClass();
    obj.setName(name);
    if (age != null) {
        if (someCondition != null)) {
            if (someCondition.test(something)) {
                obj.setAge(age);
            }
        } else {
            obj.setAge(age);
        }
    }
    return obj;
}

我的答案是保持简单。建设者的职责是构建一个对象。不提供复杂的DSL来评估条件。所以你的第二个片段非常好

为了避免代码重载,许多
if
检查与对构建器的调用交织在一起,只需将这些检查的代码提取到方法。所以你可以从

Builder builder = Builder.name("name").id("id");
if (complexCondition) {
    builder.age(age);
}

最后,bu提取出4条第一行,以一种方法计算并返回年龄,以

Builder builder = Builder.name("name").id("id").age(computeAge());
我个人更喜欢以下缩进方式,在我看来,这使它更可读,更易于调试:

Builder builder = Builder.name("name")
                         .id("id")
                         .age(computeAge());

警告!大多数生成器要求您重新分配生成器变量。你下面的例子会给你带来麻烦

Builder builder = Builder.name("name").id("id");
 if(complexCondition){
     builder.age(age);
 }
你应该习惯这种格式

Builder builder = Builder.name("name").id("id");
 if(complexCondition){
     builder = builder.age(age);
 }

我倾向于使用三元运算符来继续链

假设我有你的案例:

Builder builder = Builder
    .name("name")
    .id("id");
builder = (complexCondition ? builder.age(age) : builder)
    .occupation("brick-layer")
    .disposition("angry");
这样,您就可以在链中插入可选项,而不会完全中断它的流程。如果它很长,显然要在多行上格式化它

您可以做的另一件事是在age方法中处理null,如下所示:

public SomeClass build() {
    SomeClass obj = new SomeClass();
    obj.setName(name);
    if (age != null && someCondition != null && someCondition.test(something)) {
        obj.setAge(age);
    }
    return obj;
}
Builder builder = Builder
    .name("name")
    .id("id")
    .age(complexCondition ? age : null);
public Builder age(Integer age) {
    if (age != null) {
        this.age = age;
    }
    return this;
}
当然,在内部,您的年龄方法如下所示:

public SomeClass build() {
    SomeClass obj = new SomeClass();
    obj.setName(name);
    if (age != null && someCondition != null && someCondition.test(something)) {
        obj.setAge(age);
    }
    return obj;
}
Builder builder = Builder
    .name("name")
    .id("id")
    .age(complexCondition ? age : null);
public Builder age(Integer age) {
    if (age != null) {
        this.age = age;
    }
    return this;
}

你的第二个片段在我看来非常好。你不喜欢它的什么地方?构建者的工作是累积零件并构建最终对象。不评估条件,也不能在一行中做任何你想做的事情。它们都是有效的。重点是第一个-不是生成器的工作,第二个-将生成器模式拆分为每个条件+3行。当我有一个条件的时候没关系,但是我有10个以上的参数,5个以上的条件,在这一点上会变得很混乱。如果你有10个条件,你需要编写10个条件的代码,不管解决方案是什么。试图在一条线上传递所有信息会让事情变得更加混乱。如果你真的想保留一行,你可以使用
int age=defaultAgeValue;如果(complexCondition){age=somethingElse;}
,然后使用生成器。当然,年龄的计算可以提取到一种方法。因此,它可以成为
Builder.name(“name”).id(“id”).age(computeAge()).build()
。我要寻找的是一个解决方案,而不需要a)将复杂的检查或布尔值传递给Builder(不是他的工作,根据定义进行检查)——b)不需要在调用builderWell的每个条件检查内部调用中添加3行,而不是
Builder.name(“name”).id(“id”).age(computeAge()).build()
符合所有这些要求?关键是-如果我没有条件怎么办。有两种可能性我要么有条件,要么没有。你关于拆分条件和参数的建议更适合于此-但我不太确定这是构建者的工作来评估。在这一点上我很困惑,因此我提出了这个问题。我看不到sim如果条件是可选的(即仅在传递给构建器时进行计算),您可以在我建议的
build()中进行简单更改
方法进行解释。我将编辑。在调用生成器之前对条件进行评估,即布尔结果已经存在calculated@Sarief有人建议使用谓词作为优化,因为我假设您的条件很复杂(基于您给它的名称)。我认为只在必要时评估条件可能更有效。在这种情况下,当然会是这样,只是我的情况不同:)是的,这就是我所寻找的:D我有时会与生成器混淆,因为将null传递给方法实际上不会改变结果。谢谢不,生成器不是“不变的”。它也不会在每次添加变量或返回自身时创建新实例。如果它引起这样的麻烦,那就意味着有人把实现搞砸了。生成器的目的是减少在设置/更改不可变对象时创建的对象数量。在答案中加上负号,如果证明错误,将删除。否则,请收回答案