otice: 本文作者只是设计模式、Guice和依赖注入的初学者,所以本文不会指出使用Guice的实现方法有什么好处,所写的代码未必是最佳实践,欢迎提出改进意见。
Abstract Factory 模式 http://www.riabook.cn/doc/designpattern/AbstractFactory.htm
使用Guice实现的时候,可以将其中的MacWidgetFactory和WindowsWidgetFactory合并为一个WidgetFactory类:
public class WidgetFactory implements IWidgetFactory {
IButton button;
ITextField textField;
@Inject
public WidgetFactory(IButton button, ITextField textField){
this.button = button;
this.textField = textField;
}
public IButton getButton() {
return button;
}
public ITextField getTextField() {
return textField;
}
}
然后需要表现依赖关系的模块类,如对Windows有WindowsWidgetModule,表示需要Windows接口时将创建一个Windows的对象,并注入
import com.google.inject.AbstractModule;
public class WindowsWidgetModule extends AbstractModule {
@Override
protected void configure() {
bind(IButton.class).to(WindowsButton.class);
bind(ITextField.class).to(WindowsTextField.class);
bind(IWidgetFactory.class).to(WidgetFactory.class);
}
}
此时只需要在CustomDialog 的setWidgetFactory方法中加上@Inject注解即可使用了。
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
public class CustomDialog {
private IButton button;
private ITextField textField;
// 由于客户端只依赖于抽象的工厂,工厂如何实作并无关客户端的事
// 要抽换工厂并不需要改动客户端的程式
@Inject
public void setWidgetFactory(IWidgetFactory widgetFactory) {
setButton(widgetFactory.getButton());
setTextField(widgetFactory.getTextField());
}
public void layoutAllComponents() {
// layout all components
}
// 这边也是依赖抽象,实际改变了元件实例
// 客户端代码也不用更改
public void setButton(IButton button) {
this.button = button;
}
public void setTextField(ITextField textField) {
this.textField = textField;
}
public void showDialog() {
this.paintDialog();
button.paintButton();
textField.paintTextField();
}
public void paintDialog() {
System.out.println("custom dialog paints....");
}
public static void main(String[] args){
//CustomDialog dia = new CustomDialog(new MacWidgetFactory());
CustomDialog dia = new CustomDialog();
dia.setWidgetFactory(new WindowsWidgetFactory());
dia.showDialog();
System.out.println("use guice");
Injector injector = Guice.createInjector(new WindowsWidgetModule());
injector.getInstance(CustomDialog.class).showDialog();
}
}
可以看到 Guice可以再类的方法上加入了@Inject注解,并完成注入的。
同理若需要对Mac做模块化,只要加入一个MacWidgetModule即可
import com.google.inject.AbstractModule;
public class MacWidgetModule extends AbstractModule {
@Override
protected void configure() {
bind(IButton.class).to(MacButton.class);
bind(ITextField.class).to(MacTextField.class);
bind(IWidgetFactory.class).to(WidgetFactory.class);
}
}