在Java中将内核模型转换为输出模型

时间:2011-11-18 08:09:52

标签: java inheritance casting instanceof

这里我有一些代码将内核模型“转移”到外部插件的“输出”模型。

为此,我基于传递的OldConnection的具体子类型创建新实例,并将旧实例传递(使用强制转换)到构造函数中,因此我可以轻松地维护getter和setter的内部数据。

因此,OldIncoming,OldOutgoing和OldExpected是OldConnection的子类型。 MyNewIncoming,MyNewOutgoing和MyNewExpected是MyNewConnection的子类型。不幸的是,我无法改变内核模型,我需要构造函数中的具体类型。

代码看起来很丑陋,但我无法找到更好的解决方案,任何想法?

private MyNewConnection createIConnectedSubtypeInstance(OldConnection connection) {

    if (connection instanceof OldIncoming){
        return new MyNewIncoming((OldIncoming) connection);
    }
    if (connection instanceof OldOutgoing){
        return new MyNewOutgoing((OldOutgoing) connection);
    }
    .
    .
    .
    if (connection instanceof OldExpected){
        return new MyNewExpected((OldExpected) connection);
    }

    return new MyNewConnection(connection);
}

3 个答案:

答案 0 :(得分:1)

您可能会重载工厂方法:

private MyNewConnection createIConnectedSubtypeInstance(OldIncoming conn) {
   return new MyNewIncoming(conn);
}

private MyNewConnection createIConnectedSubtypeInstance(OldOutgoing conn) {
   return new MyNewOutgoing(conn);
}
...

正如Thomas在他的回答中指出的那样,只有在使用正确的静态类型调用这些方法时才会有效:

OldIncoming a;
...
MyNewConnection b = createIConnectedSubtypeInstance(a); // will return MyNewIncoming

由于重载使用静态绑定,因此在这种情况下不能使用OldConnection。如果这不是你的选择,那么你将在某个时候停留在做instanceof。

答案 1 :(得分:1)

替代方案是一堆重载方法,如下所示:

private MyNewIncoming createIConnectedSubtypeInstance( OldIncoming connection ) {
  return new MyNewIncoming( connection );
}

然而,只有当调用者知道connection的类型时,它才有效,否则你必须依赖那些instanceof检查。

在这种情况下,您还可以使用一些映射OldClass-&gt; NewClass并使用反射来创建实例,但我怀疑除非您需要巨大的数量的映射,否则这将是值得的麻烦。< / p>

示例:

Map<Class<? extends OldConnection>, Class<? extends NewConnection>> mapping; //initializing is up to you

public NewConnection  createIConnectedSubtypeInstance(OldConnection connection) {
  try {
    Class<? extends NewConnection> subtype = mapping.get( connection.getClass() );
    return subtype.getConstructor( connection.getClass() ).newInstance( connection );
  } catch( Exception e) { //you might want to catch the more specific types
    //handle appropriateley
  }
} 

请注意,这取决于直接映射的connection类。如果映射超类,如果找不到实际connection类的映射,则可能需要检查它们。

此外,这依赖于新实例的构造函数来接受映射类类型的一个参数。

答案 2 :(得分:0)

您可以将包装器的创建移动到OldConnection及其派生类。在OldConnection中,定义了方法

public MyNewConnection createNewConnectiom() {
    return MyNewConnection(this);
}

OldIncoming覆盖

public MyNewConnection createNewConnectiom() {
    return MyNewIncoming(this);
}

并在OldExpected覆盖

public MyNewConnection createNewConnectiom() {
    return MyNewExpected(this);
}

以这种方式你摆脱了分支和演员阵容。