我想在一些即將開展的工作中使用構建器模式,這種工作在層次結構中有幾個類。基類將有至少9個字段開始,並且各個子類可以在每個字段中添加2-4個個更多個字段。這將非常迅速地失控,建設者模式對我來說正是因爲這個原因。我初步接觸了書籍和文章中的建築模式。他們很有幫助,但對如何擴展這種模式一無所知。我試圖自己實現這一點,但是我遇到了每個子類的構造函數的麻煩,因爲我沒有得到如何將構建器中收集的數據傳遞給超類。我看了一些答案,這是我發現的。其中如何與一個抽象的助洗劑延伸一個抽象類給出一個例子使用抽象構建器vs具體類和具體構建器擴展抽象類
這一個是從SO 24243240。它也是基於這個blog post。
public abstract class AbstractA {
protected String s;
protected int i;
protected AbstractA() {
}
protected abstract static class ABuilder<T extends AbstractA, B extends ABuilder<T,B>> {
protected T object;
protected B thisObject;
protected abstract T getObject(); //Each concrete implementing subclass overrides this so that T becomes an object of the concrete subclass
protected abstract B thisObject(); //Each concrete implementing subclass builder overrides this for the same reason, but for B for the builder
protected ABuilder() {
object = getObject();
thisObject = thisObject();
}
public B withS(String s) {
object.s = s;
return thisObject;
}
public B withI(int i) {
object.i = i;
return thisObject;
}
public T build() {
return object;
}
}
}
public final class ConcreteA extends AbstractA {
private String foo;
protected ConcreteA() {
}
public static final class Builder extends AbstractA.ABuilder<ConcreteA,Builder> {
@Override protected ConcreteA getObject() {
return new ConcreteA();
}
@Override protected Builder thisObject() {
return this;
}
public Builder() {
}
public Builder withFoo(String foo) {
object.foo = foo;
return this;
}
}
}
然後在客戶端代碼,它看起來像......
ConcreteA baz = new ConcreteA.Builder().withFoo("foo").withS("bar").withI(0).build();
我喜歡這個例子,因爲它可以讓你輕鬆地擴展這些類,但它似乎也對我來說,這違背使用構建器模式的目的,因爲方法withS(String s)
和withI(int i)
的行爲很像setter方法。此外,此方法將基類和構建器類的字段保留爲受保護而非私有。
這裏有一個從SO 17164375
public class NutritionFacts {
private final int calories;
public static class Builder<T extends Builder> {
private int calories = 0;
public Builder() {}
public T calories(int val) {
calories = val;
return (T) this;
}
public NutritionFacts build() { return new NutritionFacts(this); }
}
protected NutritionFacts(Builder builder) {
calories = builder.calories;
}
}
public class GMOFacts extends NutritionFacts {
private final boolean hasGMO;
public static class Builder extends NutritionFacts.Builder<Builder> {
private boolean hasGMO = false;
public Builder() {}
public Builder GMO(boolean val) {
hasGMO = val;
return this;
}
public GMOFacts build() { return new GMOFacts(this); }
}
protected GMOFacts(Builder builder) {
super(builder);
hasGMO = builder.hasGMO;
}
}
我喜歡這一個看似更緊密地堅持由喬希布洛赫描述的建設者模式,它也可以讓你簡單地生成器傳遞到構造函數需要類實例化。這將是一個不錯的方式之前做的建設者內一些驗證實例在調用build()
的對象。與此同時,雖然,這個例子說明如何擴展與具體類生成器模式,當你做到這一點自帶的擴展的具體類(如不一致的接口,繼承方法的所有污穢的潛力,其可以破壞的狀態你的對象,等)
所以我的問題是沒有實現與一個抽象的生成器,也可以讓你在構造函數的基類的引用到建築商通過一個抽象類的方法嗎?喜歡的東西:
public abstract BaseClass {
// various fields go here
...
public abstract Builder<T extends BaseClass, B extends Builder<T,B>> {
// add chaining methods here
...
public T build() {
if (isValid()) return new T(this);
else Throw new IllegalArgumentException("Invalid data passed to builder.");
}
}
public BaseClass(Builder builder) {
// set fields of baseclass here
}
}
我知道你不能實例化一個對象,我在這裏顯示的方式,但有一些其他的方式來做到這一點我的意思嗎?這可能是工廠會去的地方嗎?也許我只是對建設者模式有一些錯誤的假設。 :)如果是這樣,是否有更好的方向?
我知道這是有點晚,但你的答案!當時我的主管告訴我完全避免了構建模式,因爲Beans需要有getter和setter方法。我很天真,希望實施一個「聰明」的解決方案。 – maester999