2011-06-16 7 views
5

tengo una fábrica me gusta volver a implementar el uso de Guice:parametrizada con Guice

enum MyObjects { OBJECT1, OBJECT2, ... } 
class Object1 implements SomeInterface { ... } 
class Object2 implements SomeInterface { ... } 
... 
class Factory { 
    public static SomeInterface createObject(MyObjects obj) { 
    switch (obj) { 
    case OBJECT1: return new Object1(); 
    case OBJECT2: return new Object2(); 
    ... 
    } 
    } 

¿Hay una manera fácil de ponerlo en práctica? Algo como Provider.get (parámetro) y el uso de enlaces para definir qué objeto se debe utilizar en cada caso?

Respuesta

5

Tiene varias opciones aquí.

1. ya que se utiliza un enum distinguir entre implementaciones, entonces usted tiene un número finito de las implementaciones que se pueden definir cada uno con su propia unión, siempre y cuando use una anotación durante la inyección

public @interface SomeInterfaceKind { 
    MyObjects value(); 
} 

en su Module:

bind(SomeInterface.class) 
    .annotatedWith(new SomeInterfaceKindImpl(MyObjects1.OBJECT1) 
    .to(Object1.class); 
... 

Luego, en las clases a inyectar: ​​

@Inject void setSomeInterface(
    @SomeInterfaceKind(MyObjects.OBJECT1) SomeInterface object) {...} 

Aquí hay que definir SomeInterfaceKindImpl clase que implementa SomeInterfaceKind (sí, es posible extender una anotación!) Para más detalles, echa un vistazo a cómo se implementa en Named Guice.

2. También puede utilizar Guice MapBinder de la siguiente manera (me resulta más sencillo de implementar)

en el módulo:

MapBinder.newMapBinder(MyObjects.class, SomeInterface.class) 
    .addBinding(MyObjects.OBJECT1).to(Object1.class); 
MapBinder.newMapBinder(MyObjects.class, SomeInterface.class) 
    .addBinding(MyObjects.OBJECT2).to(Object2.class); 

Luego, en métodos inyectadas:

@Inject void setSomeInterface(Map<MyObjects, SomeInterface> map) { 
    SomeInterface object1 = map.get(MyObjects.OBJECT1); 
    ... 
} 
+0

gracias por la respuesta. Según tengo entendido, la primera opción es más apropiada cuando en tiempo de compilación se conoce la clase real, mientras que la segunda opción permite la decisión en el tiempo de ejecución qué implementación usar. –

4

También puede usar la inyección asistida

public interface Factory { 

    public Object1 createObject1(String param1); 
    public Object2 createObject2(Date param2); 

} 


public class Object1 { 
    @AssistedInject 
    public Object1(String param1) { 
      // do something 
    } 
} 

public class Object2 { 
    @AssistedInject 
    public Object2(Dateparam2) { 
     // do something 
    } 
} 

Luego, en su módulo

install(new FactoryModuleBuilder() 
    .implement(Object1.class, Object1.class) 
    .implement(Object2.class, Object2.class) 
    .build(Factory.class)); 

continuación, puede utilizar la fábrica donde usted lo necesita

@Inject 
private Factory factory;