代码之家  ›  专栏  ›  技术社区  ›  Jon

Java中的包装器工厂

  •  0
  • Jon  · 技术社区  · 17 年前

    我可能把自己设计成了这个问题的一个角落,但我觉得有一个可行的已知解决方案来解决我没有看到的问题。很可能我把问题完全复杂化了,跳过了显而易见的解决方案。如有任何建议,将不胜感激。

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

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

    现在,使情况复杂化的部分是,我正在尝试创建一个列表,在添加之前自动用适当的包装器包装适当的类型。比如:

    -- 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 回复  |  直到 17 年前
        1
  •  1
  •   Varkhan    17 年前

    我认为您应该在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泛型的一个常见限制。

        2
  •  0
  •   paulmurray    17 年前

    是的,我也碰到过这种事。我已经得出结论,实体不应该被包装在接口中。一个实体——一个可变值bean——不是一个服务,包装它只会带来无尽的痛苦。

    接口意味着每个名义上返回bean列表的方法(这是一个非常常见的事情)都必须声明为返回 List<? extends BeanInterface> ,您必须提供方法,这些方法的工作是在这些列表中创建新元素(您不能只在其中放入bean)。谚语中的痛苦。

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