Оберточная фабрика на Яве - PullRequest
0 голосов
/ 27 марта 2009

Возможно, я загнал себя в угол с этой проблемой, но я чувствую, что есть практичное известное решение для чего-то такого, чего я не вижу. Вполне может быть, что я полностью усложнил проблему и пропустил очевидное решение. Любой совет будет принята с благодарностью.

У меня есть набор объектов, определенных как интерфейсы. У каждого есть конкретная реализация и реализация оболочки. Например:

-- 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 ]

1 голос
/ 27 марта 2009

Я думаю, вы должны добавить 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.

0 голосов
/ 27 марта 2009

Да, я тоже сталкивался с такими вещами. Я пришел к выводу, что объекты не должны быть заключены в интерфейсы. Сущность - изменяемый bean-компонент - не является службой, и ее обертывание просто вызывает бесконечное горе.

Интерфейсы означают, что каждый метод, который номинально возвращает список bean-компонентов - очень распространенная вещь - должен быть объявлен как возвращающий List<? extends BeanInterface>, и вы должны предоставить методы, задачей которых является создание новых элементов в этих списках не могу просто положить туда боб). Боль в пословице.

Используйте интерфейсы экономно, когда сущности действительно реализуют какой-то общий шаблон, общий для некоторых из ваших сущностей.

...