本文將從以下幾個方面對子類 builder() 缺少父類屬性進行詳細闡述:
一、Subclassing with the Builder Pattern
在實現 builder 模式時,我們通常使用一個基礎的 builder 類來構建對象。然而,有時候我們需要在繼承中使用 builder 模式,此時存在一個問題:子類的 builder 沒有繼承父類的屬性。
例如,假設我們有一個基礎的汽車類 Car,它有三個屬性:make、model、year。我們想要實現一個 Tesla 類,它是 Car 的子類,然而它有一個額外的屬性:battery。
class Car {
private final String make;
private final String model;
private final int year;
// Constructor
private Car(Builder builder) {
this.make = builder.make;
this.model = builder.model;
this.year = builder.year;
}
// Builder class
public static class Builder {
private final String make;
private final String model;
private final int year;
public Builder(String make, String model, int year) {
this.make = make;
this.model = model;
this.year = year;
}
public Car build() {
return new Car(this);
}
}
}
class Tesla extends Car {
private final int battery;
private Tesla(TeslaBuilder builder) {
super(builder);
this.battery = builder.battery;
}
public static class TeslaBuilder extends Builder {
private int battery;
public TeslaBuilder(String make, String model, int year) {
super(make, model, year);
}
public TeslaBuilder battery(int battery) {
this.battery = battery;
return this;
}
public Tesla build() {
return new Tesla(this);
}
}
}
可以看到,在子類 Tesla 中,我們需要創建一個 TeslaBuilder 去構建 Tesla 對象。然而,在子類中,TeslaBuilder 並沒有繼承 Car.Builder 的屬性。
二、解決方法
1. 使用父類的靜態工廠方法
父類可以提供一個靜態的工廠方法,用於從子類的 builder 中構建父類實例。這種方法可以將父類的屬性添加到子類 builder 中,並在子類的 build() 方法中調用父類的 build() 方法。
class TeslaBuilder extends Builder {
private int battery;
public static TeslaBuilder newBuilder() {
return new TeslaBuilder();
}
private TeslaBuilder() {
super("Tesla", "Model S", 2019);
}
public TeslaBuilder battery(int battery) {
this.battery = battery;
return this;
}
@Override
public Car build() {
return new Tesla(this);
}
}
class Tesla extends Car {
private final int battery;
private Tesla(TeslaBuilder builder) {
super(builder);
this.battery = builder.battery;
}
// Static factory method
public static TeslaBuilder newBuilder() {
return TeslaBuilder.newBuilder();
}
}
在上面的代碼中,TeslaBuilder 繼承自 Car.Builder。我們使用父類 Car 的靜態工廠方法來創建一個名為 “Tesla” 的實例,同時,我們也可以在子類 TeslaBuilder 中添加子類的屬性 “battery”。
此外,在 TeslaBuilder 的 build() 方法中,我們調用了父類 Car 的 build() 方法來創建 Tesla 對象。
2. 通過抽象方法繼承
另一種解決方法是,使用抽象方法來實現屬性的繼承。
abstract class Car {
protected final String make;
protected final String model;
protected final int year;
protected Car(CarBuilder builder) {
this.make = builder.make;
this.model = builder.model;
this.year = builder.year;
}
public static abstract class CarBuilder<e b="" car,="" carbuilder> {
protected String make;
protected String model;
protected int year;
public B make(String make) {
this.make = make;
return self();
}
public B model(String model) {
this.model = model;
return self();
}
public B year(int year) {
this.year = year;
return self();
}
public abstract E build();
protected abstract B self();
}
}
class Tesla extends Car {
private final int battery;
private Tesla(TeslaBuilder builder) {
super(builder);
this.battery = builder.battery;
}
public static class TeslaBuilder extends CarBuilder {
private int battery;
public TeslaBuilder battery(int battery) {
this.battery = battery;
return self();
}
@Override
public Tesla build() {
return new Tesla(this);
}
@Override
protected TeslaBuilder self() {
return this;
}
}
}
在上面的代碼中,我們使用了一個抽象方法 self() 來返回 builder 對象。通過讓子類的 builder 實現該方法,我們可以保證屬性的繼承問題。在 TeslaBuilder 的 build() 方法中,我們返回了 Tesla 對象。
三、小結
子類 builder() 缺少父類屬性是 builder 模式中的一種常見問題。本文介紹了兩種方法來解決這個問題:靜態工廠方法和抽象方法繼承。在實現 builder 模式時,選擇哪種方法需要根據實際情況來決定。
原創文章,作者:NNSGS,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/373931.html