我一直在寻找实现具有许多子类的 Builder 模式,并通过@Josemy找到了这个答案。但是,它只有 1 个级别的子类:. 我试图将构建器模式用于更复杂的层次结构,但失败了。Pizza -> SomePizza
我有以下类层次结构:
Stuff
/ \
Food Drink
| |
Pizza Juice
/ \ / \
| SicilianPizza | OrangeJuice
| AppleJuice
CaliforniaPizza
每个类都有一个应该设置的字段,其中一些字段是强制性的 (ob) 并且必须传递,有些是可选的 (op) 并且可以通过构建器设置:
Stuff -> double price (op)
Food -> String mealType (op)
Pizza -> List<String> toppings (op), int size (ob)
CaliforniaPizza -> boolean addOlives (op)
SicilianPizza -> boolean addCheese (op)
Drink -> double density (ob), double alcoholVolume (op)
Juice -> String color (op)
AppleJuice -> String appleColor (op)
OrangeJuice -> int orangeSize (op)
我使用建造者来建造比萨饼和饮料:
TestStuff.java:
public class TestStuff {
public static void main(String[] args) {
CaliforniaPizza californiaPizze = CaliforniaPizza.builder(2)
.addTopping("Tomatoes").addOlives(true).build();
SicilianPizza sicilianPizza = SicilianPizza.builder(1)
.addTopping("Bacon").addCheese(false).build();
AppleJuice appleJuice = AppleJuice.builder(40)
.setPrice(120).setAlcoholVolume(0).setAppleColor("yellow").build();
OrangeJuice orangeJuice = OrangeJuice.builder(35).setOrangeSize(8).build();
}
}
这些是我的课程:
东西.java:
public abstract class Stuff {
protected double price;
protected Stuff() {}
protected abstract class Builder<T extends Builder> {
protected abstract Stuff build();
protected abstract T self();
public T setPrice(double price) {
Stuff.this.price = price;
return (T) self();
}
}
}
食物.java :
public abstract class Food extends Stuff {
protected String mealType; //breakfast/dinner/etc
protected Food() {}
public abstract class Builder<T extends Builder> extends Stuff.Builder<Builder> {
protected abstract Food build();
protected abstract T self();
public T setMealType(String mealType) {
Food.this.mealType = mealType;
return (T) self();
}
}
}
比萨.java :
public abstract class Pizza extends Food {
protected List<String> toppings = new ArrayList<>(); //optional
protected int size; //obligatory
protected Pizza(int size) {this.size = size;}
public abstract class Builder<T extends Builder> extends Food.Builder<Builder> {
public T addTopping(String topping) {
toppings.add(topping);
return (T) self();
}
}
}
CaliforniaPizza.java :
public class CaliforniaPizza extends Pizza {
private boolean addOlives;
private CaliforniaPizza(int size) {super(size);}
public static Builder builder(int size) {return new CaliforniaPizza(size).new Builder();}
public class Builder extends Pizza.Builder<Builder> {
@Override
public CaliforniaPizza build() {
return CaliforniaPizza.this;
}
@Override
public Builder self() {return this;}
public Builder addOlives(boolean addOlives) {
CaliforniaPizza.this.addOlives = addOlives;
return this;
}
}
}
西西里披萨.java :
public class SicilianPizza extends Pizza {
private boolean addCheese;
private SicilianPizza(int size) {super(size);}
public static Builder builder(int size) {
return new SicilianPizza(size).new Builder();
}
public class Builder extends Pizza.Builder<Builder> {
@Override
public SicilianPizza build() {return SicilianPizza.this;}
@Override
public Builder self() {return this;}
public Builder addCheese(boolean addCheese) {
SicilianPizza.this.addCheese = addCheese;
return this;
}
}
}
饮料.java :
public abstract class Drink extends Stuff {
protected double density;
protected double alcoholVolume;
protected Drink(double density) {this.density = density;}
public abstract class Builder<T extends Builder> extends Stuff.Builder<Builder> {
protected abstract Drink build();
protected abstract T self();
public T setAlcoholVolume(double alcoholVolume) {
Drink.this.alcoholVolume = alcoholVolume;
return (T) self();
}
}
}
果汁.java :
public abstract class Juice extends Drink {
private String color;
protected Juice(double density) {super(density);}
public abstract class Builder<T extends Builder> extends Drink.Builder<Builder> {
public Builder setColor(String color) {
Juice.this.color = color;
return (T) self();
}
}
}
苹果汁.java :
public class AppleJuice extends Juice {
private String appleColor;
private AppleJuice(double density) {super(density);}
public static Builder builder(double density) {return new AppleJuice(density).new Builder();}
public class Builder extends Juice.Builder<Builder> {
@Override
public AppleJuice build() {
return AppleJuice.this;
}
@Override
public Builder self() {
return this;
}
public Builder setAppleColor(String appleColor) {
AppleJuice.this.appleColor = appleColor;
return this;
}
}
}
橙汁.java :
public class OrangeJuice extends Juice{
private int orangeSize;
private OrangeJuice(double density) {super(density);}
public static Builder builder(double density) {return new OrangeJuice(density).new Builder();}
public class Builder extends Juice.Builder<Builder> {
@Override
public OrangeJuice build() {return OrangeJuice.this;}
@Override
public Builder self() {return this;}
public Builder setOrangeSize(int orangeSize) {
OrangeJuice.this.orangeSize = orangeSize;
return this;
}
}
}
这段代码有几个问题:
@Override
注解上面build()
和self
内部CaliforniaPizza
,并SicilianPizza
在观的Intellij和错误信息被高亮显示表示,方法不从其超类重写方法。虽然Juice
子类中没有这样的错误。TestStuff
: AppleJuice appleJuice = AppleJuice.builder(40)
.setPrice(120).setAlcoholVolume(0)
.setAppleColor("yellow").build();
给出错误:setAppleColor
用红色突出显示,无法解决。原因是setAlcoholVolume
返回 aDrink.Builder
而不是AppleJuice.Builder
。同时,如果我setAlcoholVolume
在builder()
方法之后立即调用它会返回Juice.Builder
:
builder()
。但是对于食物,我的选择是有限的:那里没有食物setMealType
。
return (T) self()
在Juice
and 中的setter 中有一行Pizza
。但是,只有在内部Juice
,我才会收到有关未经检查的演员的警告:而在Pizza
我根本没有收到任何警告。
I have suspicions that at least problems 2 and 3 have to do with type erasure. An AppleJuice.Builder
gets passed to Juice.Builder
as T
, but then the Juice.Builder<AppleJuice.Builder>
gets passed to Drink.Builder<Juice.Builder>
and the information about AppleJuice
gets lost. Then Drink.Builder<Juice.Builder>
gets passed to Stuff.Builder<Drink.Builder>
and only information about Drink.Builder
is retained. Thus when I call setPrice(120)
right away, it returns Drink.Builder
instead of Juice.Builder
. If I'm correct, what is the way to fix it? And what are the reasons behind another issues I've encountered?
The cast
protected abstract T self();
public T setPrice(double price) {
Stuff.this.price = price;
return (T) self();
}
self()
already returns T
. The cast is unnecessary.
Unresolved methods
public abstract class Stuff {
// ...
protected abstract class Builder<T extends Builder> {
Builder
is a generic type, but it's used a raw type here. It needs the type parameter, like java.lang.Enum
.
protected abstract class Builder<T extends Builder<T>> {
Again in subtypes.
public abstract class Food extends Stuff {
// ...
public abstract class Builder<T extends Builder> extends Stuff.Builder<Builder>
同样在这里我们想StuffBuilder
用T
.
public abstract class Builder<T extends Builder> extends Stuff.Builder<T>
在@Override
小号
对类型进行排序后,覆盖问题应该会消失。
编辑:
所以我已经完成并更改了代码。(添加package
,import
并删除public
从class
ES进行编译的一个斑点。)Eclipse是满意的,除了未使用的变量。
package pizza;
import java.util.*;
class TestStuff {
public static void main(String[] args) {
CaliforniaPizza californiaPizze = CaliforniaPizza.builder(2)
.addTopping("Tomatoes").addOlives(true).build();
SicilianPizza sicilianPizza = SicilianPizza.builder(1)
.addTopping("Bacon").addCheese(false).build();
AppleJuice appleJuice = AppleJuice.builder(40)
.setPrice(120).setAlcoholVolume(0).setAppleColor("yellow").build();
OrangeJuice orangeJuice = OrangeJuice.builder(35).setOrangeSize(8).build();
}
}
abstract class Stuff {
protected double price;
protected Stuff() {}
protected abstract class Builder<T extends Builder<T>> {
protected abstract Stuff build();
protected abstract T self();
public T setPrice(double price) {
Stuff.this.price = price;
return self();
}
}
}
abstract class Food extends Stuff {
protected String mealType; //breakfast/dinner/etc
protected Food() {}
public abstract class Builder<T extends Builder<T>> extends Stuff.Builder<T> {
protected abstract Food build();
protected abstract T self();
public T setMealType(String mealType) {
Food.this.mealType = mealType;
return self();
}
}
}
abstract class Pizza extends Food {
protected List<String> toppings = new ArrayList<>(); //optional
protected int size; //obligatory
protected Pizza(int size) {this.size = size;}
public abstract class Builder<T extends Builder<T>> extends Food.Builder<T> {
public T addTopping(String topping) {
toppings.add(topping);
return self();
}
}
}
class CaliforniaPizza extends Pizza {
private boolean addOlives;
private CaliforniaPizza(int size) {super(size);}
public static Builder builder(int size) {return new CaliforniaPizza(size).new Builder();}
public class Builder extends Pizza.Builder<Builder> {
@Override
public CaliforniaPizza build() {
return CaliforniaPizza.this;
}
@Override
public Builder self() {return this;}
public Builder addOlives(boolean addOlives) {
CaliforniaPizza.this.addOlives = addOlives;
return this;
}
}
}
class SicilianPizza extends Pizza {
private boolean addCheese;
private SicilianPizza(int size) {super(size);}
public static Builder builder(int size) {
return new SicilianPizza(size).new Builder();
}
public class Builder extends Pizza.Builder<Builder> {
@Override
public SicilianPizza build() {return SicilianPizza.this;}
@Override
public Builder self() {return this;}
public Builder addCheese(boolean addCheese) {
SicilianPizza.this.addCheese = addCheese;
return this;
}
}
}
abstract class Drink extends Stuff {
protected double density;
protected double alcoholVolume;
protected Drink(double density) {this.density = density;}
public abstract class Builder<T extends Builder<T>> extends Stuff.Builder<T> {
protected abstract Drink build();
protected abstract T self();
public T setAlcoholVolume(double alcoholVolume) {
Drink.this.alcoholVolume = alcoholVolume;
return (T) self();
}
}
}
abstract class Juice extends Drink {
private String color;
protected Juice(double density) {super(density);}
public abstract class Builder<T extends Builder<T>> extends Drink.Builder<T> {
public Builder<T> setColor(String color) {
Juice.this.color = color;
return self();
}
}
}
class AppleJuice extends Juice {
private String appleColor;
private AppleJuice(double density) {super(density);}
public static Builder builder(double density) {return new AppleJuice(density).new Builder();}
public class Builder extends Juice.Builder<Builder> {
@Override
public AppleJuice build() {
return AppleJuice.this;
}
@Override
public Builder self() {
return this;
}
public Builder setAppleColor(String appleColor) {
AppleJuice.this.appleColor = appleColor;
return this;
}
}
}
class OrangeJuice extends Juice{
private int orangeSize;
private OrangeJuice(double density) {super(density);}
public static Builder builder(double density) {return new OrangeJuice(density).new Builder();}
public class Builder extends Juice.Builder<Builder> {
@Override
public OrangeJuice build() {return OrangeJuice.this;}
@Override
public Builder self() {return this;}
public Builder setOrangeSize(int orangeSize) {
OrangeJuice.this.orangeSize = orangeSize;
return this;
}
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句