2

我有一个名为 DBObject 的类,它返回两个不同的类对象。如果输入字符串是水,则返回 object1,否则返回 object2。

我的要求是,现在它基于 if else 返回对象......但将来会添加更多对象。那么,除了使用使代码静态的 elseif 之外,是否有任何动态方式来返回类对象?

我的意思是我可以在这种情况下使用任何 Java 设计模式吗?

代码:

if(str=="water")
 return new object1()
else if...
     return new object3()
else if...
     return new object4()
else if...
     return new object5()
else if...
     return new object6()  
else
  return new object2()
4

4 回答 4

4

首先,替换if(str=="water")if("water".equals(str))。运算符==比较引用,而方法equals()比较对象。

其次,有几种方法。第一个是使用动态类加载:Class.forName(className). 在您的情况下,您可以在符号名称和完全限定的类名称之间保存映射,因此您的代码将如下所示:

Class.forName(map.get(str)).newInstance()

如果您的具体类列表不是那么动态,您可以将enum其用作工厂:

enum Factory {
    red {
        public Color create() {
            new Red();
        }
    },
    green {
        public Color create() {
            new Green();
        }
    };

    public abstract Color create();
}

String colorName = ...;
Color c = Factory.valueOf(colorName).create();

展望未来,您可以使用例如 SPI 的可用实现的动态发现:

于 2012-09-06T10:46:55.347 回答
2

您在这里谈论的是实施级别,而不是设计级别。对于实现,您需要Java Reflection,您可以像这样使用它:

Object obj = Class.forName(type).newInstance();

在设计层面抽象工厂是最接近的模式。

于 2012-09-06T10:42:52.243 回答
2

您可以使用映射,使用 String 作为键和 java.lang.Class 作为值。您的类可能共享一个公共超类或接口,您可以在映射定义中将其指定为泛型类型参数:

Map<String, Class<? extends SomeSuperClass>> types = new HashMap<String, Class<? extends SomeSuperClass>>();
types.put("water", object1.class);

您可以使用反射来创建类的实例(有关更多信息,请参见http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html):

SomeSuperClass instance = types.get("water").newInstance();
于 2012-09-06T10:43:42.073 回答
0

我会用枚举替换那个字符串。显然,它具有有限数量的具有特殊含义的值,每个只需要一个实例 - 完全适合枚举。另外,您可以获得更好的类型安全性;如果构造无效,则某人不能"fire"作为参数传入。

如果你这样做:

public enum ObjectType {
    WATER,
    AIR,
    EARTH
}

public static Foo createObject(ObjectType objType) {
    switch (objType) {
        case WATER: return new object1();
        case AIR:   return new object2();
        case EARTH: return new object3();
        default: // throw new IllegalArgumentException or something similar
    }
}

我认为这很容易理解,并且随着接口的发展而相当稳定。

如果创建对象更复杂,那么new object1()您可能希望维护某种工厂对象的映射(仍然关闭枚举),而不是在案例中显式编码逻辑。那么该createObject方法的逻辑本质上是factoryMap.get(objType).constructInstance().

于 2012-09-06T10:44:05.357 回答