2016-06-13 59 views
0

我有一个类的集合,称它们为Derived1, Derived2, ..., Derived6,每个类都是基类Base的子类。这些类是在第三方Java包中定义的。下面的OOP设计有更好的选择吗?

我正在写一个类,将写出这些对象的人类可读的表示。我按如下方式处理了这个问题:定义方法String transform(Derivedi object),对于每个i=1,2,...,6String transform(Base object)

问题发生在例如Base obj = new Derived3(...)和我想计算obj的表示形式时。表达式transform(obj)调用带有签名String transform(Base)的方法,该方法必须调用“正确”方法(在这种情况下是具有签名String transform(Derived3)的方法)。

方法String transform(Base object)委托人通过if (obj instanceof Derivedi)形式的条件语句对每个i=1,2,...,6工作到适当的方法。 (如果我有对包的控制权,我将在基类上有一个抽象方法String toReadable(),这对每个派生类都必须实现;不幸的是,在这种情况下我无法控制包)。

我不像这个解决方案一样(很容易看出原因)。 String transform(Base)的这个实现有什么替代方案?

+0

我不明白这个问题怎么可能出现。你有没有考虑重写'toString()'方法?或者您所描述的类层次结构中的另一个简单覆盖?而不是别的需要参数的地方? – EJP

+0

这不是多态,多态性将调用所有对象上的相同方法(如您提到的toReadable()方法)。这里有一个内置的Java机制,每个Class都有一个从Object继承的toString()方法,可以为特定于类的行为重写,也许给予您的类重写它。如果不是,则必须求助于非OO解决方案,例如if-else序列。请记住,无论何时你有一个开关情况,或者在这种情况下,它是丑陋的if-else序列表亲,你可以用你正在检查的行为值的映射替换它。 –

回答

1

您可以尝试并为每个班级提供变压器(包含transform(...)的对象)。然后保持一张将变换器映射到这些类的映射(假设变换器本身是无状态的)。

例子:

class Transformer { 
    Class<? extends Base> getTransformableClass() { ... } 
    String transform(Base obj){ 
    //check and cast obj to the actual type then create the string 
    } 
} 

Map<Class<?>, Transformer> transformers = ...; 
Transformer base = new BaseTransformer(); //the same for derived 
transformers.put(base.getTransformableClass(), base); 

注意与CDI /反射,你可以稍微做自动查找(即查找实现某个接口或具有一定的注释进行注释的所有类)。

然后使用它是这样的:

public String transform(Base obj) { 
    //add null checks etc. 

    return transformers.get(obj.getClass()).transform(obj); 
}  

还应注意的是仿制药可能有助于实现变压器,但使用它们从地图则会使一些铸件/原始类型的必要,因为你不知道实际的时你从地图上得到的类型,即你作为开发人员知道transformers.get(Derived1.class)应该返回一个能够处理Derived1实例的变换器,但是编译器不知道这一点,因此需要你处理并适当地进行转换。

0

您可以使用getSimpleName()获取类的名称,并在名称上使用switch语句。您仍然需要在transform(Base object)中完成这个授权,但会比几个if语句和instanceof检查更清晰。