0

我有Foo.java,这是界面。

以及许多实现它的类。Bar1.java , Bar2.java等等

我在前端有一个方法,就像这样:getBar(String bar)

我可以这样做:

if(bar.equals("Bar1")) {
    return new Bar1();
}

但是我能以某种方式做到这一点,即每次都有新的实现Foo.java,那么我不必用新的ELSE语句来更新我的方法。

我认为每个实现都有唯一的 ID 或其他东西,BarX.java每当我创建它时我都会添加它。

有什么建议或想法吗?我想也许我可以使用enum或 smthing 或任何其他解决方案。

4

6 回答 6

2

仅供参考:当然,您意识到您不应该这样写:

if(bar == "Bar1") {
    return new Bar1();
}

你应该这样做:

if("Bar1".equals(bar)) {
    return new Bar1();
}

看起来你需要一个工厂(又名虚拟构造函数)。如果你所有的 Foo 实现者都有一个默认构造函数,你可以这样做:

public class FooFactory {

    public static Foo create(Class<Foo> clazz) {
        return clazz.newInstance();
    }

    public static Foo create(String className) {
        return create(Class.forName(className));
    }
}

有异常需要处理;我没有时间为你拼写出来。你应该看到这个想法。您需要做的就是编写一个新类,您的工厂可以处理它。

如果还有其他构造函数,只需用参数和附加调用详细说明主题。这应该让你开始。

于 2012-10-04T13:34:07.860 回答
2

对我来说听起来像是依赖注入反射的工作。

你可以做 :

Class myClass = Class.forName("my.namespace.MyClass");

那将是反思。不是很好,但做的工作。

于 2012-10-04T13:35:28.033 回答
1

您可以按类名创建对象:

Class<?> clazz = Class.forName(className);
Object object = ctor.newInstance();

或者,如果您需要调用特定的构造函数(例如,使用一个String参数strArgument):

Constructor<?> c = clazz.getConstructor(String.class);
Object object = c.newInstance(new Object[] { strArgument });
于 2012-10-04T13:38:08.523 回答
0

这是一个经典的工厂模式问题。

解决方案是每当您必须维护静态 Map 并且每当您有新的“Bar”类型时,您都需要首先在地图中注册它,因此无论何时您想要该类型的对象,您都可以简单地从地图中选择它。

考虑以下类

interface IVehicle {
    public void drive();
    public void stop();
}

class Car implements IVehicle {

    public void drive(){
        //logic goes here
    }

    public void stop(){
        //logic goes here
    }
}

class VehicleFactory{

    public IVehicle createVehicle(String VehicleType){
        IVehicle vehicle = null;

        if("Car".equalsIgnoreCase(VehicleType) ){
            vehicle = new Car();
        }
        if("Bus".equalsIgnoreCase(VehicleType) ){
            //vehicle = new Bus();
        }
        if("Train".equalsIgnoreCase(VehicleType) ){
            //vehicle = new Train();
        }
        return vehicle;
    }
}

因此,每当您拥有一种新型车辆时,您都必须通过添加新车辆类型的代码来更改方法。

解决方案是改进 VehicleFactory 类,如下所示,所有车辆类型都应在地图中注册,如下所示。

class Car implements IVehicle {

    static{
        VehicleFactoryFlexible.registerVehicle("Car", new Car());
    }
    public void drive(){
        //logic goes here
    }

    public void stop(){
        //logic goes here
    }

    public IVehicle createVehicle(){
        return (IVehicle) new Car();
    }
}

public class VehicleFactoryFlexible {

    static Map vehicleRegistry = new HashMap();

    public static void registerVehicle(String vehicleType, IVehicle veh){
        vehicleRegistry.put(vehicleType, veh);
    }

    public IVehicle createVehicle(String vehicleType){
        IVehicle vehicle = (IVehicle)vehicleRegistry.get(vehicleType);
        return vehicle.createVehicle();
    }
}
于 2012-10-04T13:40:18.903 回答
0

- Reflection是要走的路...

-但你仍然可以使用这样的方法

public static Foo createObj(Class<Foo> clazz) {
    return clazz.newInstance();
}

-是的,值得一提的是,它应该是equals()不是 ==

if(bar.equals("Bar1")) {
    return new Bar1();
}
于 2012-10-04T13:43:18.090 回答
0

使用反射,您可以扫描整个包中的所有 BarX 类,并使用此列表实例化您的输入是否存在于列表中。或者您可以直接使用 Class.forName 解决方案来捕获错误。编辑:看看这个http://code.google.com/p/reflections/

于 2012-10-04T13:49:26.067 回答