我有以下工厂类:
public class MessagePresenterCreator implements IPresenterFactory{
@Override
public MessagePresenter createPresenter(Message m) {
if (m instanceof Letter) {
return new LetterPresenter();
}
if (m instanceof Cable) {
return new CablePresenter();
}
if (m instanceof Postcard) {
return new PostcardPresenter();
}
throw new IllegalArgumentException();
}
}
我可以通过以下界面配置guice以自动生成并提供此类工厂:
public interface IPresenterFactory {
public abstract MessagePresenter createPresenter(Message m);
}
答案 0 :(得分:4)
我喜欢以两种方式来考虑工厂 - 仅仅从组件中组装对象的工厂,以及在该组件中进行条件逻辑的工厂。
你的工厂背后有逻辑。 Guice无法自动化该逻辑,因为它只是处理依赖关系的连接。如果您创建的类型需要一些注入的依赖项,并且只是在创建时提供了一些内容,那么工厂的自动连接可以使用guice的AssistedInject extension来完成。这将允许您提供工厂接口,使用@AssistedInject注释所创建类型中的任何字段,并且guice的扩展将创建一个工厂实现类,它将注入Injector中绑定的任何内容,并且还会传递这些create()参数。但是在这种情况下,所有Guice和AssistedInject正在做的就是将各个部分拉在一起 - 根据事先指定的配方进行连接。它不会在最后一刻做出关于它们的决定。
您正在提供对象的条件创建。那不行。
An idea above提到制作一个依赖于类型映射到演示者的工厂 - 例如:
Map<Class<? extends Message>, Class<? extends MessagePresenter>>
如果您将其与Multibinder的MapBindings结合使用,这是一种很好的方法。 (我得加强那些文档...嗯)
使用这种方法,您可以创建一个可扩展的工厂 - 定义Message的初始映射 - &gt; MessagePresenter子类,但在以后可以打开其他映射的可能性,而无需更改工厂 - 只需在multibinder上绑定更多映射,如下所示:
MapBinder<String, Snack> mapbinder = MapBinder.newMapBinder(
binder(),
new TypeLiteral<Class<? extends Message>>(){},
new TypeLiteral<Class<? extends MessagePresenter>>(){});
mapbinder.addBinding(MyMessage.class).toInstance(MyMessagePresenter.class);
mapbinder.addBinding(YourMessage.class).toInstance(YourMessagePresenter.class);
您可以在任意数量的模块中执行此操作,使用映射添加更多类型以进行切换。
答案 1 :(得分:1)
没有guice没有像这样的工厂。你可以写一个工厂,用Map<Class<? extends Message>, Class<? extends MessagePresenter>
并使用反射。这样,如果这是您的目标,您可以在guice模块中进行管理。
public class MessagePresenterCreator implements IPresenterFactory{
private final Map<Class<? extends Message>, Class<? extends MessagePresenter> mapping;
public MessagePresenterCreator(Map<Class<? extends Message>, Class<? extends MessagePresenter> mapping) {
this.mapping = mapping;
}
@Override
public MessagePresenter createPresenter(Message m) {
Class<? extends MessagePresenter> clazz = mapping.get(m);
if (clazz == null) {
throw new UnsupportedOperationException();
}
return clazz.newInstance();
}
}