1. 程式人生 > 實用技巧 >六個建立型模式之抽象工廠模式

六個建立型模式之抽象工廠模式

工廠三兄弟:簡單工廠模式,工廠方法模式,抽象工廠模式我選最優講解,以後其他的設計模式都選用改良版最優模式講解,其他的請自行百度。

工廠方法模式通過引入工廠等級結構,解決了簡單工廠模式中工廠類職責太重的問題,但由於工廠方法模式中的每個工廠只生產一類產品,可能會導致系統中存在大量的工廠類,勢必會增加系統的開銷。此時,我們可以考慮將一些相關的產品組成一個“產品族”,由同一個工廠來統一生產,這就是我們本文將要學習的抽象工廠模式的基本思想。 介面面板庫的初始設計(案例) Sunny軟體公司欲開發一套介面面板庫,可以對Java桌面軟體進行介面美化。為了保護版權,該面板庫原始碼不打算公開,而只向用戶提供已打包為jar檔案的class位元組碼檔案。使用者在使用時可以通過選單來選擇面板,不同的面板將提供視覺效果不同的按鈕、文字框、組合框等介面元素,其結構示意圖如圖所示:

完整解決方案:

Sunny公司開發人員使用抽象工廠模式來重構介面面板庫的設計,其基本結構如圖所示:

介面面板庫結構圖:

在圖中,SkinFactory介面充當抽象工廠,其子類SpringSkinFactory和SummerSkinFactory充當具體工廠,介面Button、TextField和ComboBox充當抽象產品,其子類SpringButton、SpringTextField、SpringComboBox和SummerButton、SummerTextField、SummerComboBox充當具體產品。完整程式碼如下所示:

按鈕:

//在本例項中我們對程式碼進行了大量簡化,實際使用時,介面元件的初始化程式碼較為複雜
//按鈕介面:抽象產品 interface Button { public void display(); }
//Spring按鈕類:具體產品
class SpringButton implements Button {
     public void display() { 
          System.out.println("顯示淺綠色按鈕。");
     }
}
//Summer按鈕類:具體產品
class SummerButton implements Button {
     public void display() { 
          System.out.println(
"顯示淺藍色按鈕。"); } }

文字框:

//文字框介面:抽象產品
interface TextField {
    public void display();
}
//Spring文字框類:具體產品
class SpringTextField implements TextField {
    public void display() { 
        System.out.println("顯示綠色邊框文字框。");
    }
}
//Summer文字框類:具體產品
class SummerTextField implements TextField {
    public void display() { 
          System.out.println("顯示藍色邊框文字框。");
     }
}

組合框:

//組合框介面:抽象產品
interface ComboBox {
    public void display();
}
//Spring組合框類:具體產品
class SpringComboBox implements ComboBox {
    public void display() { 
         System.out.println("顯示綠色邊框組合框。");
    }
}
//Summer組合框類:具體產品
class SummerComboBox implements ComboBox {
    public void display() { 
         System.out.println("顯示藍色邊框組合框。");
    }
}

開始建立介面面板工廠:

//介面面板工廠介面:抽象工廠
interface SkinFactory {
    public Button createButton();
    public TextField createTextField();
    public ComboBox createComboBox();
}
//Spring面板工廠:具體工廠
class SpringSkinFactory implements SkinFactory { 
     public Button createButton() {
         return new SpringButton();
     }

     public TextField createTextField() { 
         return new SpringTextField();
     }

     public ComboBox createComboBox() { 
         return new SpringComboBox();
     }
}
//Summer面板工廠:具體工廠
class SummerSkinFactory implements SkinFactory {
     public Button createButton() { 
         return new SummerButton();
     }

     public TextField createTextField() { 
         return new SummerTextField();
     }

     public ComboBox createComboBox() { 
         return new SummerComboBox();
     }
}

為了讓系統具備良好的靈活性和可擴充套件性,我們引入了工具類XMLUtil和配置檔案,

XMLUtil類的程式碼如下所示:

import javax.xml.parsers.*; 
import org.w3c.dom.*;
import org.xml.sax.SAXException; 
import java.io.*;

public class XMLUtil {
        //該方法用於從XML配置檔案中提取具體類類名,並返回一個例項物件
        public static Object getBean() {
            try {
                //建立文件物件
                DocumentBuilderFactory dFactory = DocumentBuilderFactory
                DocumentBuilder builder = dFactory.newDocumentBuilder();
                Document doc;
                doc = builder.parse(new File("config.xml"));
                //獲取包含類名的文字節點
                NodeList nl = doc.getElementsByTagName("className");
                Node classNode = nl.item(0).getFirstChild();
                String cName = classNode.getNodeValue();
                //通過類名生成例項物件並將其返回
                Class c = Class.forName(cName);
                Object obj = c.newInstance();
                return obj;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
      }
}

配置檔案config.xml中儲存了具體工廠類的類名,程式碼如下所示:

<?xml version="1.0"?>
<config>
    <className>SpringSkinFactory</className>
</config>

編寫如下客戶端測試程式碼:

class Client {
     public static void main(String args[]) {
           //使用抽象層定義SkinFactory factory;
           Button bt; TextField tf; ComboBox cb;
           factory = (SkinFactory)XMLUtil.getBean(); 
           bt = factory.createButton();
           tf = factory.createTextField(); 
           cb = factory.createComboBox(); 
       bt.display(); tf.display(); cb.display(); } }

編譯並執行程式,輸出結果如下:

顯示淺綠色按鈕。
顯示綠色邊框文字框。
顯示綠色邊框組合框。

如果需要更換面板,只需修改配置檔案即可,在實際環境中,我們可以提供視覺化介面,例如選單或者視窗來修改配置檔案,使用者無須直接修改配置檔案。如果需要增加新的面板,只需增加一族新的具體元件並對應提供一個新的具體工廠,修改配置檔案即可使用新的面板, 原有程式碼無須修改,符合“開閉原則”。