我正在寻找一个干净的模式来解决以下问题:
我有几种类型的车辆(比方说Car,Bike和Truck,所有这些类都扩展了抽象类Vehicle)。每种类型的车辆都有几个特定的属性。
我有一个车辆清单,我需要建立一个GUI,使用户能够选择车辆,并编辑其属性。我想要实现的结果是在左侧显示车辆列表(使用JList),在右侧显示包含编辑所选车辆所需字段的面板。
我知道如何在列表只包含一种类型的项目时使用它(我在左边使用Jlist,在右边使用自定义JPanel)。我为每个子类制作了一个自定义面板:CarPanel,BikePanel ...... 我的问题是所选车辆的类型与相应的面板之间的联系。虽然它会起作用,但我想避免这样的事情:
if (selectedVehicle instanceof Car) {
useThisPanel(new CarPanel((Car)selectedVehicle));
} ...
因为它对我来说似乎不太可维护。
我也想避免像useThisPanel(selectedVehicle.getPanel())
之类的东西,因为没有理由任何车辆类应该知道它的显示方式
我正在努力将我的代码转换为MVC模式,但在我看来它并不是解决我的问题。
我很确定我不是第一个面对此问题的人,但我无法找到任何答案或建议来管理这种情况。
答案 0 :(得分:1)
以OO方式解决此问题的常用方法是使用visitor pattern:
public interface VehicleVisitor<T> {
T visitCar(Car car);
T visitTruck(Truck truck);
T visitBike(Bike bike);
}
public abstract class Vehicle {
public abstract <T> T accept(VehicleVisitor<T> visitor);
}
public class Car extends Vehicle {
@Override
public <T> T accept(VehicleVisitor<T> visitor) {
return visitor.visitCar(this);
}
}
// same for Bike and Truck
最后
public class SomeClass {
private JPanel createPanelFor(Vehicle vehicle) {
return vehicle.accept(new VehicleVisitor<JPanel>() {
@Override
public JPanel visitCar(Car car) {
return new CarPanel(car);
}
// same for Truck and Bike
}
}
}
这一切都很干净,但它比基于简单实例的解决方案更难理解。它有一个优点:你不能忘记处理一个新的Vehicle类型:它会强制你实现抽象的accept()
方法,这会强制你向Visitor接口添加另一个方法,这将迫使你在每个访问者中实现它。