gpt4 book ai didi

Java builder 模式——抽象 builder

转载 作者:行者123 更新时间:2023-11-30 06:16:19 27 4
gpt4 key购买 nike

首先,我对 Java 比较陌生,所以我问的可能是微不足道的,但我在这里或其他地方找不到答案。

为简单起见,假设我有以下类层次结构:

class Shape {
protected Shape(double x, double y) {...}
}

class Circle extends Shape {
public Circle(double radius) {...}
}

class Rectangle extends Shape {
public Rectangle(double edge) {...}
}

我想为每个形状使用构建器模式。所以我为他们每个人都添加了构建器:

class Shape {
protected static abstract class BuilderBase<T extends BuilderBase<T, S>, S extends Shape> {
public T setLocation(double x, double y) {
// ...
return (T)this; // ? - is there a way to avoid this casting?
}

public abstract S build();
}

protected Shape(/*...*/) {/*...*/}
}

class Circle extends Shape {
public static class Builder extends BuilderBase<Builder, Circle> {
public Builder setRadius(double radius) {
//...
return this;
}

@Override
public Circle build() { return new Circle(/*...*/); }
}

private Circle(/*...*/) {/*...*/}
}

class Rectangle extends Shape {
public static class Builder extends BuilderBase<Builder, Rectangle> {
public Builder setRadius(double radius) {
//...
return this;
}

@Override
public Rectangle build() {
return new Rectangle(/*...*/);
}
}

public Rectangle(/*...*/) {/*...*/}
}

编辑:这里使用泛型是为了允许以任何顺序使用 Builder 方法。例如,为了允许以下调用:

new Circle.Builder()
.setLocation(0, 0)
.setRadius(10)
.build();

我的问题出在这个转换中:

public T setLocation(double x, double y) {
// ...
return (T)this; // ? - is there a way to avoid this casting?
}

我正在努力寻找避免这种转换的方法。到目前为止我发现的唯一方法是向 BaseBuilder 方法添加另一个抽象方法:

protected static abstract class BuilderBase<T extends BuilderBase<T, S>, S extends Shape> {
protected abstract T getBuilder();

public T setLocation(double x, double y) {
// ...
return getBuilder();
}

//...
}

因此每个派生构建器都必须实现它:

@Override
protected Circle getBuilder() {
return this;
}

在我看来这有点矫枉过正,但我​​不想收到编译警告。

问题:有没有更优雅的方法来避免强制转换?

最佳答案

你无法避免为每个子类添加一些额外的代码,但你可以避免未经检查的强制转换。只需创建一个 abstract 方法,负责返回适当类型的 this。此方法必须由具体子类实现一次,但可用于应返回 this 的基类的所有方法:

class Shape {
protected static abstract
class BuilderBase<T extends BuilderBase<T, S>, S extends Shape> {
/** all subclasses should implement {@code self()} as {@code return this;} */
abstract T self();
public T setLocation(double x, double y) {
// ...
return self();
}
public T setFooBar(FooBar x) {
// ...
return self();// the more methods you have the more useful self() becomes
}

public abstract S build();
}

protected Shape(/*...*/) {/*...*/}
}

class Circle extends Shape {
public static class Builder extends BuilderBase<Builder, Circle> {
@Override final Builder self() { return this; }

public Builder setRadius(double radius) {
//...
return this;
}

@Override
public Circle build() { return new Circle(/*...*/); }
}

private Circle(/*...*/) {/*...*/}
}

class Rectangle extends Shape {
public static class Builder extends BuilderBase<Builder, Rectangle> {
@Override final Builder self() { return this; }

public Builder setRadius(double radius) {
//...
return this;
}

@Override
public Rectangle build() {
return new Rectangle(/*...*/);
}
}

public Rectangle(/*...*/) {/*...*/}
}

关于Java builder 模式——抽象 builder ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27530750/

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