六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 24|回复: 0

抽象工厂模式

[复制链接]

升级  48.67%

33

主题

33

主题

33

主题

秀才

Rank: 2

积分
123
 楼主| 发表于 2013-1-28 18:15:18 | 显示全部楼层 |阅读模式
假如你要制作一个对话框控件,你希望这个对话框可以有不同的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();  
•          }  
•      }  
•  }
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表