为几个子类创建généricGUI

时间:2013-05-13 16:04:00

标签: java user-interface

我正在寻找一个干净的模式来解决以下问题:

我有几种类型的车辆(比方说Car,Bike和Truck,所有这些类都扩展了抽象类Vehicle)。每种类型的车辆都有几个特定的​​属性。

我有一个车辆清单,我需要建立一个GUI,使用户能够选择车辆,并编辑其属性。我想要实现的结果是在左侧显示车辆列表(使用JList),在右侧显示包含编辑所选车辆所需字段的面板。

我知道如何在列表只包含一种类型的项目时使用它(我在左边使用Jlist,在右边使用自定义JPanel)。我为每个子类制作了一个自定义面板:CarPanel,BikePanel ...... 我的问题是所选车辆的类型与相应的面板之间的联系。虽然它会起作用,但我想避免这样的事情:

if (selectedVehicle instanceof Car) {
    useThisPanel(new CarPanel((Car)selectedVehicle));
} ...

因为它对我来说似乎不太可维护。

我也想避免像useThisPanel(selectedVehicle.getPanel())之类的东西,因为没有理由任何车辆类应该知道它的显示方式

我正在努力将我的代码转换为MVC模式,但在我看来它并不是解决我的问题。

我很确定我不是第一个面对此问题的人,但我无法找到任何答案或建议来管理这种情况。

1 个答案:

答案 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接口添加另一个方法,这将迫使你在每个访问者中实现它。