【问题标题】:Wrapper Factory in JavaJava中的包装器工厂
【发布时间】:2009-03-27 18:41:30
【问题描述】:

我可能已经将自己设计为解决这个问题,但我觉得有一个可行的已知解决方案来解决我没有看到的类似问题。很可能是我完全把问题复杂化了,跳过了明显的解决方案。任何建议将不胜感激。

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

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

我能做些什么来在这里制作一个有点干净的工厂方法吗?还是因为类型擦除,我现在已经不走运了?

【问题讨论】:

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


    【解决方案1】:

    我认为您应该将 WrapperFactory 添加到 WrappingList,并在构造函数中提供实际的工厂实现。比如:

    -- 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】:

    是的,我也遇到过这种事情。我已经得出结论,实体不应该被包装在接口中。实体 - 可变值 bean - 不是服务,包装它只会导致无尽的悲伤。

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

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

    【讨论】:

    • 我大体上同意——这实际上是一个重构,因为我需要使某些实体在子类中可观察。
    猜你喜欢
    • 2011-05-07
    • 2010-12-26
    • 1970-01-01
    • 1970-01-01
    • 2010-10-05
    • 1970-01-01
    • 1970-01-01
    • 2019-08-30
    • 1970-01-01
    相关资源
    最近更新 更多