我有一個回傳物件的工廠:
public class Factory {
public static Vehicle getVehicle(Options options) {
if (options.getType().equals("car")) return new Car(options);
if (options.getType().equals("moped")) return new Moped(options);
}
}
工廠創建的物件應該能夠將特定于類的選項作為引數:
public class Car extends Vehicle {
public Car(final CarOptions carOptions) { this.carOptions = carOptions; }
}
public class Moped extends Vehicle {
public Moped(final MopedOptions mopedOptions) { this.mopedOptions = mopedOptions; }
}
選項類:
public class Options {
// methods
}
public class CarOptions implements Options {
// methods
}
public class Moped implements Options {
// methods
}
如何給該Factory.getVehicle方法一個通用Options引數并將其傳遞給工廠創建的物件?我可以Factory.getVehicle(new CarOptions())很好地呼叫,但在工廠本身內部,物件需要特定型別的Options.
所需型別:CarOptions 提供:Options
我認為因為CarOptions實作Options了我可以將它作為引數傳遞給new Car(options)但似乎并非如此。
我試圖通過使用泛型來解決這個問題,但還沒有找到可行的解決方案。
uj5u.com熱心網友回復:
要給出Factory.getVehicle泛型Options,這個介面必須是泛型的:Options<V extends Vehicle>. 現在您的實作可以設定他們的規范:
CarOptions implements Options<Car>
MopedOptions implements Options<Moped>
由于您的Car/Moped建構式需要特定的Options實作,因此您必須將引數轉換為getVehicle. 對于通用回傳值,您還必須強制轉換:
public static <V extends Vehicle> V getVehicle(Options<V> options) {
if (options.getType().equals("car")) { // or options instanceof CarOptions?
return (V) new Car((CarOptions) options);
}
if (options.getType().equals("moped")) { // or options instanceof MopedOptions?
return (V) new Moped((MopedOptions) options);
}
return null;
}
編輯:訪客模式
要擺脫這些強制轉換,您可以使用訪問者模式。因此你必須改變你的工廠。請注意,方法不得為static. 如果你有更多的車輛,你必須為它添加一個方法。
public Car visit(CarOptions options) {
return new Car(options);
}
public Moped visit(MopedOptions options) {
return new Moped(options);
}
您還必須將抽象方法添加V visit(Factory visitor);到interface Options<V extends Vehicle>. 實作就是這么簡單:
public class CarOptions implements Options<Car> {
// other methods
@Override
public Car visit(Factory visitor) {
return visitor.visit(this);
}
}
public class MopedOptions implements Options<Moped> {
// other methods
@Override
public Moped visit(Factory visitor) {
return visitor.visit(this);
}
}
使用此模式,無需檢查getType()或instanceof。你可以簡單地打電話Car car = new CarOptions().visit(new Factory());
uj5u.com熱心網友回復:
有無數種方法可以實作這一點,但它類似于家庭作業,所以我會堅持使用快速(不是最好的)解決方案。
第一件事是要么讓你的CarOptions和MopedOptions類extend成為Options類,要么讓Options類成為介面,我做了后者。
然后我已經設定Vehicle并Moped接受Options界面。在這里,您沒有選項屬性的類欄位。
我還更改了您嘗試在方法中獲取類詳細資訊的getVehicle()方式,以將類名與選項類名進行比較。
泛型(例如 Clazz 類)將是一種更好的方法,但我懷疑在完成多型性和繼承之后你會使用泛型??
public class Main {
public static void main(String[] args) {
Factory f = new Factory();
Options opts = new MopedOptions();
Vehicle v = f.getVehicle(opts);
System.out.println(v.getClass().getSimpleName());
//Output: "Moped"
}
}
class Factory {
public Vehicle getVehicle(Options options) {
if (options.getClass().getSimpleName().equals("CarOptions")) return new Car(options);
if (options.getClass().getSimpleName().equals("MopedOptions")) return new Moped(options);
return null;
}
}
class Vehicle {}
class Car extends Vehicle {
private final Options carOptions;
public Car(final Options carOptions) { this.carOptions = carOptions; }
}
class Moped extends Vehicle {
private final Options mopedOptions;
public Moped(final Options mopedOptions) { this.mopedOptions = mopedOptions; }
}
interface Options {
// methods
}
class CarOptions implements Options {
// methods
}
class MopedOptions implements Options {
// methods
}
- 編輯 -
我有點不清楚Car和Moped類是否“必須”處理它們各自的特定選項,但如果可以的話,只要讓它們嚴格并將選項轉換為它們的特定子實體,就像這樣
class Factory {
public Vehicle getVehicle(Options options) {
if (options.getClass().getSimpleName().equals("CarOptions"))
return new Car((CarOptions)options);
if (options.getClass().getSimpleName().equals("MopedOptions"))
return new Moped((MopedOptions)options);
return null;
}
}
class Vehicle {}
class Car extends Vehicle {
private final CarOptions carOptions;
public Car(final CarOptions carOptions) { this.carOptions = carOptions; }
}
class Moped extends Vehicle {
private final MopedOptions mopedOptions;
public Moped(final MopedOptions mopedOptions) { this.mopedOptions = mopedOptions; }
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/519877.html
標籤:爪哇仿制药
