gpt4 book ai didi

java - 使用委托(delegate)和枚举的步骤生成器模式?

转载 作者:搜寻专家 更新时间:2023-10-31 20:31:57 27 4
gpt4 key购买 nike

我正在从事这个项目,基本上这就是我想要实现的目标。

这是我的:

MyObject obj = MyObject.builder()
.withValue("string")
.withAnotherValue("string")
.build();

MyObject obj = MyObject.builder()
.withValue("string")
.withAnotherValue("string")
.withField("key", "value")
.build();

因此,步骤构建器模式强制用户按顺序使用 withValue() 方法和 withAnotherValue() 方法。 field() 方法是可选的,可以根据需要多次使用。我关注这个网站,例如 http://www.svlada.com/step-builder-pattern/

所以我想实现的是:

MyObject obj = MyObject.builder(Type.ROCK)
.withColour("blue")
.withValue("string")
.withAnotherValue("string")
.build();

MyObject obj = MyObject.builder(Type.STONE)
.withWeight("heavy")
.withValue("string")
.withAnotherValue("string")
.withField("key", "value")
.build();

因此,在 builder() 方法中,您将放置一个枚举类型,并且基于该枚举,您将出现一组不同的方法。因此对于 ROCK,withValue()withAnotherValue()withColour() 现在是强制性的。但对于 STONE withWeight()withAnotherValue()withColour() 是必需的。

我这样的事情可能吗?在过去的两天里,我一直在尝试解决这个问题,但我似乎无法让它为每种类型提供特定的方法。它只是显示了 Builder 中的所有方法。

非常感谢任何想法和帮助。

代码:

枚举

public enum Type implements ParameterType<Type> {

ROCK, STONE

}

参数类型

interface ParameterType<T> {}

我的对象

public class MyObject implements Serializable {

private static final long serialVersionUID = -4970453769180420689L;

private List<Field> fields = new ArrayList<>();

private MyObject() {
}

public interface Type {

Value withValue(String value);
}

public interface Value {

Build withAnotherValue(String anotherValue);
}

public interface Build {

MyObject build();
}

public Type builder(Parameter type) {
return new Builder();
}

public static class Builder implements Build, Type, Value {

private final List<Field> fields = new ArrayList<>();

@Override
public Build withAnotherValue(String anotherValue) {
fields.add(new Field("AnotherValue", anotherValue));
return this;
}

@Override
public Value withValue(String value) {
fields.add(new Field("Value", value));
return this;
}

@Override
public MyObject build() {
MyObject myObject = new MyObject();
myObject.fields.addAll(this.fields);
return myObject;
}
}

}

最佳答案

使用 enum 是不可能的,但是您可以使用自定义的 enum 类来做到这一点:

public final class Type<B extends MyObject.Builder> {
private final Supplier<? extends B> supplier;

private Type(Supplier<? extends B> supplier) {
this.supplier = Objects.requireNonNull(supplier);
}

public B builder() {
return supplier.get();
}

public static final Type<MyObject.RockBuilder> ROCK =
new Type<>(MyObject.RockBuilder::new);

public static final Type<MyObject.StoneBuilder> STONE =
new Type<>(MyObject.StoneBuilder::new);
}

public class MyObject {
// ...

// And this method is probably superfluous at this point.
public static <B extends MyObject.Builder> builder(Type<? extends B> type) {
return type.builder();
}
}

您可以轻松地将这种方法应用于步骤构建器,但这里有一个单独的问题。由于步骤构建器中的每个步骤都指定了返回类型中的下一步,因此您不能很容易地重用步骤接口(interface)。例如,您需要声明单独的接口(interface) RockValueStepStoneValueStep 等,因为接口(interface)本身指定了步骤顺序。

解决这个问题的唯一简单方法是,如果单独的类型(岩石、石头等)仅严格添加步骤,例如Type.ROCK 返回一个 ColourStep 并且 Type.STONE 返回一个 WeightStep,并且 ColourStep code> 和 WeightStep 返回 ValueStep:

// Rock builder starts here.
interface ColourStep { ValueStep withColour(String c); }
// Stone builder starts here.
interface WeightStep { ValueStep withWeight(String w); }
// Shared.
interface ValueStep { AnotherValueStep withValue(String v); }

然后:

public final class Type<B /* extends ABuilderStepMarker, possibly */> {
// (Constructor and stuff basically same as before.)

public static final Type<MyObject.ColourStep> ROCK =
new Type<>(/* implementation */::new);

public static final Type<MyObject.WeightStep> STONE =
new Type<>(/* implementation */::new);
}

这种事情不能用 enum 完成的原因有很多:

  • enum 不能是通用的:

    // This is an error.
    enum Type<T> {
    }
  • 尽管您可以在 enum 上声明抽象方法并使用协变返回类型覆盖它,但协变返回类型永远不可见:

    // This is valid code, but the actual type of
    // Type.ROCK is just Type, so the return type of
    // Type.ROCK.builder() is just MyObject.Builder,
    // despite the override.
    enum Type {
    ROCK {
    @Override
    public MyObject.RockBuilder builder() {
    return new MyObject.RockBuilder();
    }
    };
    public abstract MyObject.Builder builder();
    }

关于java - 使用委托(delegate)和枚举的步骤生成器模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49655371/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com