Java的包装工厂

时间:2009-03-27 18:41:31

标签: java design-patterns generics collections type-erasure

我可能已经将自己设计成了这个问题的一个角落,但我觉得有一个可行的已知解决方案,我没有看到这样的事情。很可能是我完全过度复杂化问题并跳过了明显的解决方案。任何建议都将不胜感激。

我有一组定义为接口的实体。每个都有一个具体的实现和一个包装器实现。例如:

-- 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;
    }
}

我能做些什么来制作一个有点干净的工厂方法吗?或者由于类型擦除,我现在已经运气不好了?

2 个答案:

答案 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 - 不是一个服务,包装它只会引起无尽的悲痛。

接口意味着名义上返回bean列表的每个方法 - 一个非常常见的东西 - 必须声明为返回List<? extends BeanInterface>,并且您必须提供方法,其工作是在这些列表中创建新元素(你不能只把豆子放在那里)。众所周知的痛苦。

当实体确实实现了某些实体之间共享的一些共同模式时,请谨慎使用接口。