这里我有一些代码将内核模型“转移”到外部插件的“输出”模型。
为此,我基于传递的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);
}
答案 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);
}
以这种方式你摆脱了分支和演员阵容。