2011-11-18 77 views
2

这里我已经有了一些代码来将内核模型“转移”到外部插件的“输出”模型。为此,我创建了基于传递的OldConnection的具体子类型的新实例,并将旧实例传递给构造函数,这样我就可以轻松地为getter和setter维护内部数据。在Java中将内核模型转换为输出模型

因此,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); 
} 

回答

1

另一种方法是一堆重载方法,就像这样:

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

然而,这只能在调用方知道是什么类型的connection,否则你不得不依靠这些instanceof检查。

在这种情况下,你也可以有一些映射OldClass->的NewClass和使用反射来创建实例,但我怀疑,除非你需要一个映射巨大量,这将是值得冒这个险。

实施例:

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的映射。

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

1

你可以超载工厂方法:

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

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

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

正如托马斯在他的回答指出,这将只有当你调用这些方法与正确的静态类型的工作由于重载使用静态绑定,因此在这种情况下不能使用OldConnection。如果这不是您的选择,那么您会在某个时刻停止执行instanceof。

0

您可以将包装的创建移动到OldConnection及其派生类。在OldConnection,与

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

定义的方法

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

OldIncoming覆盖和OldExpected覆盖与

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

这样,你就摆脱了分公司和铸件中。

+0

如果我理解正确,他不能更改OldConnection代码,这可能是为什么他首先需要MyNewConnection包装。 – pushy

+0

你是对的,我错过了。 +1为您的答案 – MartinZ