Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> java/android 設計模式學習筆記(4)---抽象工廠模式

java/android 設計模式學習筆記(4)---抽象工廠模式

編輯:關於Android編程

再來介紹一下抽象工廠模式(Abstact Factory Pattern),也是創建型模式之一。抽象工廠模式和工廠方法模式稍有區別。工廠方法模式中工廠類生產出來的產品都是具體的,也就是說每個工廠都會生產某一種具體的產品,但是如果工廠類中所生產出來的產品是多種多樣的,工廠方法模式也就不再適用了,就要使用抽象工廠模式了。
抽象工廠模式的起源或者最早的應用,是對不同操作系統的圖形化解決方案,比如在不同操作系統中的按鈕和文字框的不同處理,展示效果也不一樣,對於每一個操作系統,其本身構成一個工廠類,而按鈕與文字框控件構成一個產品類,兩種產品類兩種變化,各自有自己的特性,比如 Windows,Unix 和 Mac OS 下的 Button 和 Text 等。所以據此,我們可以初步構建框架:
  這裡寫圖片描述
然後對於 Windows 系統來說需要生成的是 WindowsButton 和 WindowsText 產品類對象,其他兩個系統一樣也需要對應的對象。為了達到“為創建一組相關或者是相互依賴的對象提供一個接口,而不需要指定它們的具體類”的松散耦合原則,這時使用抽象工廠模式就非常契合。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxoMSBpZD0="特點">特點

抽象工廠模式(Abstact Factory Pattern)提供一個接口,用於創建相關或依賴對象的家族,而不需要明確指明具體類。
和工廠方法模式一樣,抽象工廠模式依然符合“針對抽象編程,不針對具體類編程”的原則,將客戶端和具體類解耦,增加擴展性,契合設計模式中的依賴倒置原則和裡氏替換原則。

UML類圖

這裡以上面的不同操作系統的圖形化解決方案為例來畫出 uml 類圖(貌似圖片寬度被固定死了,在新的標簽頁中打開該圖片即可),
  這裡寫圖片描述
雖然抽象工廠模式的類繁多,但是主要還是分為 4 類:

AbstractFactory:抽象工廠角色(對應 IFactory 接口),它聲明了一組用於創建不同產品的方法,每一個方法對應一種產品,如圖中的 IFactory 接口就有 createButton 和 createText 方法用於創建 IButton 對象和 IText 對象。ConcreteFactory:具體工廠角色(對應 WindowFactory,UnixFactory 和 MacOSFactory 類),它實現了在抽象工廠中定義的創建產品的方法,生成一組具體產品,這些產品構成一個產品種類,每一個產品都位於某個產品等級結構中。AbstractProduct:抽象產品角色(對應 IButton 和 IText 接口),他定義了幾種產品的基本行為。ConcreteProduct:具體產品角色(對應WindowsButton 和 WindowsText 等 6 個實現類),它定義具體工廠生產的具體產品對象,實現抽象產品接口中聲明的業務方法。  這裡用的是一個實例的 uml 類圖,對應的抽象工廠模式的 uml 類圖只要把其中的角色換一個名字就可以了,是一樣的。

 

示例與源碼

我們直接根據上面的 uml 類圖直接構造四個角色:

產品相關類

產品類主要是 IButton 接口和其實現子類,IText 接口和其實現子類。IButton 接口和其子類:
IButton.class

public interface IButton {
    void show();
}

WindowsButton.class

public class WindowsButton implements IButton {
    @Override
    public void show() {
        Log.e("show", "this is a Windows button");
    }
}

UnixButton.class

public class UnixButton implements IButton{
    @Override
    public void show() {
        Log.e("show", "this is a Unix button");
    }
}

MacOSButton.class

public class MacOSButton implements IButton{
    @Override
    public void show() {
        Log.e("show", "this is a MacOS button");
    }
}

IText 接口和其實現子類:
IText.class

public interface IText {
    void show();
}

WindowsText.class

public class WindowsText implements IText{
    @Override
    public void show() {
        Log.e("show", "this is a Windows text");
    }
}

UnixText.class

public class UnixText implements IText{
    @Override
    public void show() {
        Log.e("show", "this is a Unix text");
    }
}

MacOSText.class

public class MacOSText implements IText{
    @Override
    public void show() {
        Log.e("show", "this is a MacOS text");
    }
}

工廠相關類

  上面定義完產品的相關類之後就要定義工廠的相關類了,工廠類的作用主要是用來創建對應的兩個產品種類的對象:
IFactory.class

public interface IFactory {
    /**
     * 生成對應按鈕
     */
    IButton createButton();

    /**
     * 生成對應文字
     */
    IText createText();
}

WindowsFactory.class

public class WindowsFactory implements IFactory {
    @Override
    public IButton createButton() {
        return new WindowsButton();
    }

    @Override
    public IText createText() {
        return new WindowsText();
    }
}

UnixFactory.class

public class UnixFactory implements IFactory{
    @Override
    public IButton createButton() {
        return new UnixButton();
    }

    @Override
    public IText createText() {
        return new UnixText();
    }
}

MacOSFactory.class

public class MacOSFactory implements IFactory{
    @Override
    public IButton createButton() {
        return new MacOSButton();
    }

    @Override
    public IText createText() {
        return new MacOSText();
    }
}

測試

  最後的測試程序也很簡單:

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.btn_Windows:
            WindowsFactory windowsFactory = new WindowsFactory();
            windowsFactory.createButton().show();
            windowsFactory.createText().show();
            break;
        case R.id.btn_Unix:
            UnixFactory unixFactory = new UnixFactory();
            unixFactory.createButton().show();
            unixFactory.createText().show();
            break;
        case R.id.btn_MacOS:
            MacOSFactory macOSFactory = new MacOSFactory();
            macOSFactory.createButton().show();
            macOSFactory.createText().show();
            break;
    }
}

對象的日志也能夠成功的打印:
這裡寫圖片描述

總結

  抽象工廠模式在 Android 源碼中的實現相對來說是比較少的,其中一個比較確切的例子是 Android 底層對 MediaPlayer 的創建,具體類圖如下所示(在新的標簽頁中打開該圖片即可):
這裡寫圖片描述
四種 MediaPlayerFactory 分別會生成不同的 MediaPlayer 基類:StagefrightPlayer、NuPlayerDriver、MidFile 和 TestPlayerStub ,四者均繼承於MediaPlayerBase 。
抽象工廠的優點有很多,一個顯著的優點是分離接口與實現,客戶端使用抽象工廠來創建需要的對象,它根本就不知道具體的實現是誰,客戶端只是面向產品的接口編程而已,使其從具體的產品實現中解耦,同時基於接口與實現的分離,使抽象工廠模式在切換產品類時更加靈活、容易。
當然缺點也是很明顯的,第一個也是最明顯的就是類文件的大大增多,第二個是如果要擴展新的產品類,就需要去修改抽象工廠類的最下層接口,這就會導致所有的具體工廠類均會被修改。

抽象工廠模式與工廠方法模式對比

其實對比一下兩種模式的 uml 圖,就可以發現其實工廠方法模式是潛伏在抽象工廠模式中的,抽象工廠中的每個方法都可以單獨抽出來作為一個工廠方法。抽象工廠的任務是定義一個負責創建一組產品的接口,這個接口內的每個方法都負責創建一個具體產品,同時我們利用實現抽象工廠的子類來提供這些具體的做法,所以在抽象工廠中利用工廠方法來實現生產方法是相當自然的做法。這麼一對比,可以知道抽象工廠模式比工廠模式的一個優點就是在它可以將一群相關的產品集合起來。
對比一下,使用場景也就清楚了:當需要創建產品家族和想讓制造的相關產品集合起來時,使用抽象工廠模式;當僅僅想把客戶代碼從需要實例化的具體類中解耦,或者如果目前還不明確將來需要實例化哪些具體類時,可以使用工廠方法模式。

源碼下載

  https://github.com/zhaozepeng/Design-Patterns/tree/master/AbstactFactoryPattern

 
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved