2011-07-07 5 views
1

J'ai une classe A qui fonctionne avec List<String>. Mais personne en dehors de cette classe ne devrait avoir besoin de savoir que cela fonctionne avec des cordes. Cependant, je veux aussi fournir l'implémentation concrète que la classe devrait utiliser pour List (via l'injection de dépendance).Dependecy Injection des collections

A devrait ressembler à ceci

public class A { 
    private ListFactory listFactory; //this gets injected from the outside 

    public A(ListFactory listFactory) { 
    this.listFactory = listFactory; 
    } 

    public void a() { 
    List<String> = listFactory.createList(); 
    //... 
    } 
} 

Et la classe appelant B quelque chose comme ça

public class B { 
    public void b() { 
    ListFactory factory = new ArrayListFactory(); //we want class A to use ArrayList 
    A a = new A(factory); 
    //... 
    } 
} 

ListFactory serait une interface qui est mis en œuvre par ArrayListFactory pour créer ArrayList s.

Quintessence: Je ne veux pas que B doit mentionner quelque part String. Et je ne veux pas non plus que A doit mentionner ArrayList quelque part.

Est-ce possible? Et comment regarder ListFactory et ArrayListFactory?

Répondre

1

C'est plus simple que vous faites, je pense:

public interface Factory { 
    public <T> List<T> create(); 
} 

public class FactoryImpl implements Factory { 
    public <T> ArrayList<T> create() { 
     return new ArrayList<T>(); 
    } 
} 

... 
Factory f = new FactoryImpl(); 
List<String> strings = f.create(); 
... 
+0

Wow. THX! Je ne connaissais même pas cette syntaxe. Je dois regarder ça ... C'est exactement ce que je voulais. – qollin

+0

Bien, j'ai raté ça aussi. –

1

Semble que vous avez écrit tout ce dont vous avez besoin. Les usines ressembleront:

interface ListFactory<K, T extends List<K>> { 
    T create(); 
} 

class ArrayListFactoryImpl implements ListFactory<String, ArrayList<String>> { 
    public ArrayList<String> create() { 
     return new ArrayList<String>(); 
    } 
} 

class Sample { 
     public static void main(String[] args) { 
      ListFactory<String, ArrayList<String>> factory = new ArrayListFactoryImpl(); 
      factory.create().add("string"); 
     } 
} 
+0

Thx ! Mais ce n'est pas tout à fait ça, car ArrayListFactoryImpl est implémenté par la "personne" qui implémente aussi la classe "B". Et cette personne ne devrait pas avoir à savoir que la classe "A" a besoin de chaînes ... Sinon, l'utilisateur de classe A doit connaître un détail d'implémentation de A (qu'il utilise des chaînes de caractères). – qollin

+0

Pourriez-vous passer d'usine à B d'ailleurs, alors? –

+0

Le problème est que l'usine connaît actuellement deux choses: Strings et ArrayList. Et personne ne devrait avoir à connaître ces deux choses, l'un étant un détail d'implémentation de A et l'autre un détail d'implémentation de B. Mais peut-être que ce n'est pas possible ... – qollin

0

Une autre tentative grâce à plus claire compréhension de la question:

interface ListFactory<T extends List> { 
    T create(); 
} 

class ArrayListFactoryImpl implements ListFactory<ArrayList> { 
    public ArrayList create() { 
     return new ArrayList(); 
    } 
} 

class ListWrapper<T> implements List<T> { 
    private final List impl; 

    public ListWrapper(List impl) { 
     this.impl = impl; 
    } 

    public boolean add(T t) { 
     if (!String.class.isAssignableFrom(t.getClass())) 
      throw new RuntimeException("Aaaaa"); 
     return impl.add(t); 
    } 

    // so on... 
} 

class A { 
    A(ListFactory factory) { 
     List<String> stringsOnly = new ListWrapper<String>(factory.create()); 
    } 
} 

class Sample { 
     public static void main(String[] args) { 
      ListFactory<ArrayList> factory = new ArrayListFactoryImpl(); 
      new A(factory); 
     } 
} 
Questions connexes