2009-03-27 11 views
0

Je me suis peut-être mal pris à l'idée de ce problème, mais j'ai l'impression qu'il existe une solution pratique à ce problème que je ne vois pas. Il se peut fort bien que je complique complètement le problème et que je saute la solution évidente. Tout avis serait grandement apprécié.Wrapper Factory en Java

J'ai un ensemble d'entités définies comme des interfaces. Chacun a une implémentation concrète et une implémentation de wrapper. Par exemple:

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

Maintenant, la partie qui est ce qui complique la situation est que je suis en train de faire une liste qui encapsule automatiquement le type approprié avec son emballage approprié avant de l'ajouter. Quelque chose comme:

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

Y at-il quelque chose que je peux faire pour faire une méthode d'usine un peu propre ici? Ou suis-je déjà pas de chance à ce stade en raison de l'effacement de type?

Répondre

1

Je pense que vous devriez ajouter une WrapperFactory à votre WrappingList, et fournir l'implémentation en usine dans le constructeur. Quelque chose comme:

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

} 

Le problème de base est que l'effacement ne vous laissera pas savoir quoi que ce soit au sujet de T dans le code réel, donc à moins que vous passez quelque chose à votre liste qui connaît sur le T spécifique que vous utilisez (par exemple, comment pour l'envelopper) vous ne pourrez rien faire. Et ce n'est pas vous concevoir dans un coin;) c'est simplement une limitation commune des génériques de Java.

+0

Je pense que c'est la réponse qui était dans ma tête et qui m'énerve que ça devrait être possible. Cela fonctionne vraiment ici. Merci! – Jon

0

Oui, j'ai aussi rencontré ce genre de problème. J'ai conclu que les entités ne devraient pas être enveloppées dans des interfaces. Une entité - un bean de valeur mutable - n'est pas un service, et l'emballer ne fait que causer un chagrin sans fin. Les interfaces signifient que chaque méthode qui retourne une liste de beans - une chose très courante - doit être déclarée comme retournant List<? extends BeanInterface>, et vous devez fournir des méthodes dont le travail consiste à créer de nouveaux éléments dans ces listes (vous pouvez pas juste mis un haricot là-dedans). Douleur dans le proverbial.

Utilisez les interfaces avec parcimonie lorsque des entités implémentent réellement un modèle commun partagé par certaines de vos entités.

+0

Je suis d'accord en général - c'était en fait un refactoring en premier lieu parce que je devais rendre certaines entités observables dans une sous-classe. – Jon