我可能已经将自己设计成了这个问题的一个角落,但我觉得有一个可行的已知解决方案,我没有看到这样的事情。很可能是我完全过度复杂化问题并跳过了明显的解决方案。任何建议都将不胜感激。
我有一组定义为接口的实体。每个都有一个具体的实现和一个包装器实现。例如:
-- Foo.java
public interface Foo {
public String getName();
}
-- FooImpl.java
public class FooImpl implements Foo {
private String name;
public String getName() {
return name;
}
}
-- AbstractWrapper.java
public class AbstractWrapper {
protected String decorate(String text) {
return "** " + text + " **";
}
-- FooWrapper.java
public class FooWrapper extends AbstractWrapper implements Foo {
private Foo wrappedFoo;
public FooWrapper(Foo wrappedFoo) {
this.wrappedFoo = wrappedFoo;
}
public String getName() {
return decorate(wrappedFoo.getName());
}
}
现在,使情况复杂化的部分是我正在尝试创建一个List,在添加它之前自动用适当的包装器包装适当的类型。类似的东西:
-- WrappingList.java
/** T is the base entity interface type. */
public class WrappingList<T> implements List<T> {
private List<T> wrappedList;
public WrappingList(List<T> wrappedList) {
this.wrappedList = wrappedList;
}
....
public boolean add(T item) {
return wrappedList.add(wrapItem(item));
}
protected T wrapItem(T item) {
T wrappedItem = .....;
return T;
}
}
我能做些什么来制作一个有点干净的工厂方法吗?或者由于类型擦除,我现在已经运气不好了?
答案 0 :(得分:1)
我认为你应该在你的WrappingList中添加一个WrapperFactory,并在构造函数中提供实际的工厂实现。类似的东西:
-- WrapperFactory.java
public class WrapperFactory<T> {
public T wrap(T item);
}
-- WrappingList.java
/**
* A self-wrapping list.
*
* @param T the stored, wrapped item type
*/
public class WrappingList<T> implements List<T> {
private List<T> wrappedList;
private WrapperFactory<T> wrapper;
public WrappingList(List<T> wrappedList, WrapperFactory<T> wrapper) {
this.wrappedList = wrappedList;
this.wrapper = wrapper;
}
....
public boolean add(T item) {
return wrappedList.add(wrapper.wrap(item));
}
}
基本问题是擦除不会让你在实际代码中知道关于T的任何信息,所以除非你把一些东西传递到你知道你正在使用的特定T的列表(例如如何包装它),否则你赢了能够做任何事情。它并不是设计你的角落;)它只是Java泛型的常见限制。
答案 1 :(得分:0)
接口意味着名义上返回bean列表的每个方法 - 一个非常常见的东西 - 必须声明为返回List<? extends BeanInterface>
,并且您必须提供方法,其工作是在这些列表中创建新元素(你不能只把豆子放在那里)。众所周知的痛苦。
当实体确实实现了某些实体之间共享的一些共同模式时,请谨慎使用接口。