2012-06-07 69 views
3

我无法找到一种方式,似乎并没有错的方式来做到这一点,下面给出如何将实现器在一个接口上转换为另一个接口?

public interface IType {} 
public interface IMode {} 

public interface Factory<T extends IType> { 
    IMode get(T o); 

    Class<T> getIType(); 
} 

我上面的接口和类的大名单的同时实现ITypeIMode与相应的工厂。

我需要能够从一个转换到另一个,例如,

public class A implements IType {} 
public class One implements IMode {} 

public class AToOne implements Factory<A> { 
    public IMode get(A o){ 
     return new One(); 
    } 

    public Class<A> getIType(){ 
     return A.class; 
    } 
} 

鉴于存在这些类的1对1映射,即对于每一个具体的IType有一个并且只有一个具体IMode与相应的工厂,我该如何将IType的列表转换为IMode的列表?

即,

private List<Factory<? extends IType>> factoryList; 

public List<IMode> getConversions(List<? extends IType> types){ 
    ??? 
} 

我第一次尝试并不那么好走,

//Fill this using the getIType() method from each factory 
Map<Class<IType>, Factory<? extends IType>> factoryList = new HashMap<Class<IType>, Factory<? extends IType>>(); 

public List<IMode> getConversions(List<IType> types){ 
    List<IMode> modes = new ArrayList<IMode>(); 

    for(IType type : types){ 
     //Derp 
     Factory<? extends IType> factory = factoryList.get(type.getClass()); 
     //Error 
     factory.get(factory.getIType().cast(type)); 
    } 
} 

错误:

The method get(capture#12-of ? extends IType) in the type 
Factory<capture#12-of ? extends IType> 
is not applicable for the arguments (capture#14-of ? extends IType) 
+0

到底什么是你的问题?您的方法背后的一般想法对我来说似乎很好。 – Voo

+0

@Voo在上面的概述中,'type.getClass()'返回的是与我放入地图中不匹配的具体类,然后我不知道如何将输入投射到工厂,确实得到了,因为不能保证它们是相同的。我写的东西没有编译。 – Andrew

+0

啊所以你的问题不是一般的设计方法,而是泛型部分。这应该很容易修复,让我试试:) – Voo

回答

2

就像我在我的评论中提到的,你只需要使用通用的辅助方法来访问地图,什么是在传递来执行从Factory<? extends IType>Factory<T>,其中T的类型相匹配的未经检查的转换:

Map<Class<? extends IType>, Factory<? extends IType>> factoryList = 
     new HashMap<Class<? extends IType>, Factory<? extends IType>>(); 

private <T extends IType> IMode convert(T iType) { 
    //unchecked cast - implementation must guarantee map holds correct data 
    Factory<T> factory = (Factory<T>)factoryList.get(iType.getClass()); 
    //then convert 
    return factory.get(iType); 
} 

您还可以从循环这个辅助方法:

public List<IMode> getConversions(List<IType> types) { 
    List<IMode> modes = new ArrayList<IMode>(types.size()); 
    for (IType type : types) { 
     IMode iMode = convert(type); 
     modes.add(iMode); 
    } 
    return modes; 
} 
+0

谢谢,这就是我最终做的事情,我还需要遍历IType的所有声明类,因为'getClass'返回的是具体类而不是接口。男人觉得很脏。 – Andrew

+0

虽然你想要的不是具体的类吗?这就是工厂地图中的关键所在。 –

+0

糟糕是啊,我的实际代码更复杂,我有扩展我具体的'IMode'类的子类。只是细节,感谢所有的帮助。 – Andrew

1

简单的解决办法是:

interface IFoo { 
} 

interface IBar { 
} 

private static class Foo implements IFoo { 
} 

private static class Bar implements IBar { 
} 

interface IFoo2IBarConverter<B extends IBar, F extends IFoo> { 
    B convert(F foo); 
} 

private static class Foo2BarConverter implements IFoo2IBarConverter<Bar, Foo> { 
    public Bar convert(Foo foo) { 
     return new Bar(); 
    } 
} 

private static class IFoo2IBarFactory { 
    private static HashMap<Class<? extends IFoo>, IFoo2IBarConverter<? extends IBar, ? extends IFoo>> converters = new HashMap<>(); 

    static { 
     converters.put(Foo.class, new Foo2BarConverter()); 
    } 

    public static<F extends IFoo, B extends IBar> B convert(F foo) { 
     // ugly unchecked cast here 
     IFoo2IBarConverter<B, F> converter = (IFoo2IBarConverter<B, F>) converters.get(foo.getClass()); 
     return converter.convert(foo); 
    } 
} 


public static void main(String[] args) { 
    Foo foo = new Foo(); 
    IBar bar = IFoo2IBarFactory.convert(foo); 
} 

您只需要一个HashMap,它将某个子类型为IFoo的特定类映射到某个转换器接口。转换器将IFoo实例转换为IBar ..实际上转换为我们想要的特定类。可悲的是,我们在IFoo2IBarFactory.convert()中得到了一个丑陋的演员阵容,我不认为有什么办法可以避开那个。至少它只是在一个本地化的位置,并与正确的评论和SuppressWarning你可以忍受它,我会认为

+0

我不确定你需要IFoo2IBarConverter接口。只要有与IBar对应的类并使用它来投射。例如'Class clazz = converters.get(foo);返回clazz.cast(foo);' – user949300

+0

@ user949300不知道我关注。是的,您可以通过使用原始对象并在'convert'内使用大型开关来获得界面,但这非常*难看,并且不会赢得我们任何东西。编辑完成后:您可以调用类对象的静态方法吗?不知道的是,我仍然会用分裂的解决方案 - 看起来更清洁。 – Voo

+0

'B extends IBar'不应该被宣布为'convert',因为主叫方决定什么是没有限制的,这很容易导致堆污染。该方法应该返回'IBar'。 –

相关问题