应用Guice依赖注入实现工厂模式[2]——Abstract Factory 模式
使用Guice依赖注入实现工厂模式[2]——Abstract Factory 模式
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); } }