抽象工厂模式
假如你要制作一个对话框控件,你希望这个对话框可以有不同的Look&Feel,最基本的想法是,使用setter将不同的Look&Feel注入到这个对话框,例如:CustomDialog.java
Java代码
1.public class CustomDialog {
2. private IButton button;
3. private ITextField textField;
4.
5. public void setButton(IButton button) {
6. this.button = button;
7. }
8.
9. public void setTextField(ITextField textField) {
10. this.textField = textField;
11. }
12.
13. public void layoutAllComponents() {
14. // ....
15. }
16.
17. public void showDialog() {
18. this.paintDialog();
19. button.paintButton();
20. textField.paintTextField();
21. }
22.
23. public void paintDialog() {
24. System.out.println("custom dialog paints....");
25. }
26.}
很简单,这是最基本的界面依赖,setter依赖于IButton和ITextField两个界面,而不是其实作类别,不过这里还有一个进一步的 要求,使用上面的方式还必须亲自调用setter、layout等方法。如果你希望皮肤的更换可以更加简单些,例如只需要透过一个元件的替换就可以完成对 话框所有元件的观感更换。
你可以使用Abstract Factory模式,将所有的对话框需要产生的元件加以封装,对话框依赖于Abstract Factory,实际上具体的Factory的实现则分别产生对话框所需要的控件,下面的UML类图将展示这种概念。
现在如果要更换所有的控件,只需要注入具体的Factory就可以了,例如:
Java代码
1.CustomDialog windowsDialog =
2. new CustomDialog(new WindowsWidgetFactory());
3.windowsDialog.showDialog();
4.
5.CustomDialog macDialog =
6. new CustomDialog(new MacWidgetFactory());
7.macDialog.showDialog();
将上面的UML图实现出来:
CustomDialog.java
Java代码
1.public class CustomDialog {
2. private IButton button;
3. private ITextField textField;
4.
5. public CustomDialog(IWidgetFactory widgetFactory) {
6. setWidgetFactory(widgetFactory);
7. }
8.
9. // 由于客户端只依赖于抽象工厂,工厂如何运作跟客户端无关。
10. // 要抽换工厂并不需要改动客户端程序
11. public void setWidgetFactory(IWidgetFactory widgetFactory) {
12. setButton(widgetFactory.createButton());
13. setTextField(widgetFactory.createTextField());
14. // ....
15. }
16.
17. public void layoutAllComponents() {
18. // layout all components
19. }
20.
21. // 这里也是依赖抽象,实际改变控件实例
22. // 客户端代码也不需要修改
23. public void setButton(IButton button) {
24. this.button = button;
25. }
26.
27. public void setTextField(ITextField textField) {
28. this.textField = textField;
29. }
30.
31. public void showDialog() {
32. this.paintDialog();
33. button.paintButton();
34. textField.paintTextField();
35. }
36.
37. public void paintDialog() {
38. System.out.println("custom dialog paints....");
39. }
40.}
IButton.java
Java代码
1.public interface IButton {
2. public void paintButton();
3.}
ITextField.java
Java代码
1.public interface ITextField {
2. public void paintTextField();
3.}
IWidgetFactory.java
Java代码
1.public interface IWidgetFactory {
2. public IButton createButton();
3. public ITextField createTextField();
4.}
MacButton.java
Java代码
1.public class MacButton implements IButton {
2. public void paintButton() {
3. System.out.println("Mac button paints....");
4. }
5.}
WindowsButton.java
Java代码
1.public class WindowsButton implements IButton {
2. public void paintButton() {
3. System.out.println("Windows button paints....");
4. }
5.}
MacTextField.java
Java代码
1.public class MacTextField implements ITextField {
2. public void paintTextField() {
3. System.out.println("Mac textField paints....");
4. }
5.}
WindowsTextField.java
Java代码
1.public class WindowsTextField implements ITextField {
2. public void paintTextField() {
3. System.out.println("Windows textField paints....");
4. }
5.}
MacWidgetFactory.java
Java代码
1.public class MacWidgetFactory implements IWidgetFactory {
2. public IButton createButton() {
3. return new MacButton();
4. }
5.
6. public ITextField createTextField() {
7. return new MacTextField();
8. }
9.}
WindowsWidgetFactory.java
Java代码
1.public class WindowsWidgetFactory
2. implements IWidgetFactory {
3. public IButton createButton() {
4. return new WindowsButton();
5. }
6.
7. public ITextField createTextField() {
8. return new WindowsTextField();
9. }
10.}
下图是Abstract Factory模式的UML结构图:
简单的说,在Abstract Factory模式中将具体的Product封装在Factory实现中,而库户仍只要面对Factory与Product的抽象界面,避免依赖于具体的 Factory与Product,由于Factory封装了所有必须的Product,所以要更换所有的控件,只需要简单地替换掉Factory的具体实 现就可以了,不需要修改客户端的程序。
事例2:
The intent of Abstract Factory is to provide for the creation of a family of related, or dependent, objects. see pic:
Additional note is below:( reference from http://www.dofactory.com) :
•AbstractFactory(ContinentFactory)
odeclares an interface for operations that create abstract products
•ConcreteFactory (AfricaFactory, AmericaFactory)
oimplements the operations to create concrete product objects
•AbstractProduct (Herbivore, Carnivore)
odeclares an interface for a type of product object
•Product(Wildebeest, Lion, Bison, Wolf)
odefines a product object to be created by the corresponding concrete factory
oimplements the AbstractProduct interface
•Client(AnimalWorld)
ouses interfaces declared by AbstractFactory and AbstractProduct classes
using the term: 产品族(Product Family),the former pic is like:
In this pattern, speaking loosely, a package is usually a "family" of classes, and an abstract factory produces a "family" of objects.
•/* GUIFactory example --
•The output should be either "I'm a WinButton" or "I'm an OSXButton"
•depending on which kind of factory was used. Note that the Application
•has no idea what kind of GUIFactory it is given or even what kind of
•Button that factory creates.*/
•
•interface GUIFactory {
• public Button createButton();
•}
•
•
•class WinFactory implements GUIFactory {
• public Button createButton() {
• return new WinButton();
• }
•}
•
•
•class OSXFactory implements GUIFactory {
• public Button createButton() {
• return new OSXButton();
• }
•}
•
•
•
•interface Button {
• public void paint();
•}
•
•
•class WinButton implements Button {
• public void paint() {
• System.out.println("I'm a WinButton");
• }
•}
•
•
•class OSXButton implements Button {
• public void paint() {
• System.out.println("I'm an OSXButton");
• }
•}
•
•
•class Application {
• public Application(GUIFactory factory){
• Button button = factory.createButton();
• button.paint();
• }
•}
•
•public class ApplicationRunner {
• public static void main(String[] args) {
• new Application(createOsSpecificFactory());
• }
•
• public static GUIFactory createOsSpecificFactory() {
• int sys = readFromConfigFile("OS_TYPE");
• if (sys == 0) {
• return new WinFactory();
• } else {
• return new OSXFactory();
• }
• }
•}
页:
[1]