抽象工廠模式(選擇產品簇)

目錄

  • 回顧眾多工廠模式
  • 抽象工廠模式的理念
  • 抽象工廠模式與工廠方法模式的差異
  • 怎么來實現(xiàn)抽象工廠模式
  • 抽象工廠模式在Android源碼中的應用

回顧眾多工廠模式

簡單工廠模式

對簡單工廠模式還不了解的可以查看下我的歷史文章 簡單工廠模式,簡單工廠模式的核心是使用工廠實現(xiàn)選擇創(chuàng)建產品實現(xiàn),這應該很好理解端衰。

簡單工廠模式

工廠方法模式

對工廠方法模式還不了解的可以查看下我的歷史文工廠方法模式拧晕。工廠方法模式的核心是將選擇創(chuàng)建產品實現(xiàn)的過程宇整,延遲到子類去完成宾符,這也是相對比較好理解的模式晃酒。

工廠方法模式

抽象工廠模式的理念

第一節(jié)的回顧故源,我們復習了簡單工廠與工廠方法模式紊遵。由此我們也會使用 UML 圖線畫出對抽象工廠模式的理解账千,然后我們在對比三張 UML 圖來分析他們之間的設計是如何演進或取舍的。

抽象工廠模式

抽象工廠模式強調了產品簇的概念暗膜,那么什么是產品簇呢匀奏?在抽象工廠模式中,產品簇是指工廠生產出的產品們之間彼此具備強關聯(lián)桦山。比如:AK47工廠生產的 AK47步槍攒射、AK47專配的子彈,一旦 AK47裝錯了子彈是無法正常開槍的(甚至會炸膛)恒水。


抽象工廠模式與工廠方法模式的差異

剛開始接觸抽象工廠模式的時候会放,我就是不能理解抽象工廠模式與工廠方法模式的區(qū)別,也許屏幕前的你也有一樣的困惑钉凌。但經過一段時間時間的思考與實踐咧最,我逐漸的明白它們之間的差異。

移動手機大賣場

工廠方法模式生產產品的形式就像 移動手機大賣場(上圖)御雕。賣場里面只賣手機矢沿,這些手機里面可能有 三星、華為酸纲、OPPO捣鲸、金立、蘋果闽坡、HTC栽惶、Nokia 等類別,但無論如何它都沒有跳出手機的范疇疾嗅。因此想買手機的客戶外厂,直接去大賣場總能挑選到心儀的手機,因為手機(工廠生產的產品實例)太多了代承。

蘋果零售店

而抽象工廠模式生產產品的形式則更像是蘋果零售店(上圖)汁蝶,除了賣手機之外還提供Mac、路由器论悴、耳機掖棉、iPad、iPod 等電子產品膀估。作為一個對品質(逼格)有要求的客戶幔亥,會直接去蘋果零售店里購買手機,一時興起再買一臺 Mac 也是可以的玖像。

無論手機大賣場蘋果零售店都是可以買到手機的,但是針對的客戶群體顯然是不一樣的。同樣的捐寥,工廠方法模式 與 抽象工廠模式 針對的客戶群體也是不一樣的笤昨,不過它們都擁有 生產產品 這一職責。

  • 工廠方法模式:讓單一產品線上的產品更易被擴展握恳。
  • 抽象工廠模式:讓多條 {單一產品線上的產品更易被擴展} 的同時瞒窒,能夠讓多條線上的產品保持約束
工廠方法&抽象工廠

如上圖乡洼,橫向有兩條產品線(手機崇裁、電腦),縱向有三個產品簇(蘋果束昵、三星拔稳、小米)。當我們不需要考慮產品簇時锹雏,為工廠方法模式巴比。反之,就是抽象工廠模式礁遵。


怎么來實現(xiàn)抽象工廠模式

目錄

可以發(fā)現(xiàn)在目錄層級上與工廠方法模式并沒有區(qū)別轻绞,差異在工廠的組織形式上。

先定義產品接口

public interface IPhone {

    void screen();

    void micro();

    void battery();

    void usb();

    // XXX just for test
    void printLog();
}

產品實現(xiàn)類

蘋果手機佣耐,及電腦的實現(xiàn)類就省略了政勃。

public class XiaoMiPhoneImpl implements IPhone {
    private String TAG = "小米手機";

    @Override
    public void screen() {
        System.out.println(TAG + "屏幕");
    }

    @Override
    public void micro() {
        System.out.println(TAG + "麥克風");
    }

    @Override
    public void battery() {
        System.out.println(TAG + "電池");
    }

    @Override
    public void usb() {
        System.out.println(TAG + "usb插口");
    }

    @Override
    public void printLog() {
        screen();
        micro();
        battery();
        usb();
    }

}

定義工廠接口

實際生活中可能無法提取工廠接口,畢竟每個工廠生產的產品不可能都保持一致兼砖。在這里定義接口的目的是想強調:這是縱向的產品簇奸远。

public interface IFactory {

    void createPhone();

    void createComputer();
}

定義小米工廠

public class XiaoMiFactoryImpl implements IFactory {
    @Override
    public void createPhone() {
        IPhone phone = new XiaoMiPhoneImpl();
        phone.printLog();
    }

    @Override
    public void createComputer() {
        IComputer computer = new XiaoMiComputerImpl();
        computer.printLog();
    }
}

客戶端調用測試

public class Client {

    public static void main(String[] args) {

        IFactory factory = new XiaoMiFactoryImpl();
        factory.createPhone();
        factory.createComputer();

    }
}

測試結果

小米手機屏幕
小米手機麥克風
小米手機電池
小米手機usb插口
小米電腦屏幕
小米電腦鍵盤
小米電腦鼠標
小米電腦usb

在理解了思想的前提下,編寫這些代碼是相當簡單的掖鱼。

抽象工廠模式在Android源碼中的應用

com.android.internal.policy.IPolicy

IPolicy 是產生窗口屏幕相關對象的抽象接口然走,在 android 源碼中,Policy 是 IPolicy 的唯一一個實現(xiàn)戏挡,用于生成對象集合芍瑞。Policy 創(chuàng)建了一系列的對象(PhoneWindow、PhoneLayoutInflater褐墅、PhoneWindowManager拆檬、PhoneFallbackEventHandler)。從UML圖就可以看出妥凳,IPolicy算是一個典型的抽象工廠竟贯,只不過在源碼中只有一個具體的工廠實現(xiàn)。

另外Policy的實現(xiàn)還有一點特殊的地方逝钥,它使用static域將他需要創(chuàng)建的對象都預先load出來屑那,也就是說當虛擬機加載Policy類的時候,就會加載它創(chuàng)建的對象的class。

定義工廠接口

public interface IPolicy {
    public Window makeNewWindow(Context context);

    public LayoutInflater makeNewLayoutInflater(Context context);

    public WindowManagerPolicy makeNewWindowManager();

    public FallbackEventHandler makeNewFallbackEventHandler(Context context);
}

定義工廠實現(xiàn)類

public class Policy implements IPolicy {
    private static final String TAG = "PhonePolicy";

    private static final String[] preload_classes = {
        "com.android.internal.policy.impl.PhoneLayoutInflater",
        "com.android.internal.policy.impl.PhoneWindow",
        "com.android.internal.policy.impl.PhoneWindow$1",
        "com.android.internal.policy.impl.PhoneWindow$DialogMenuCallback",
        "com.android.internal.policy.impl.PhoneWindow$DecorView",
        "com.android.internal.policy.impl.PhoneWindow$PanelFeatureState",
        "com.android.internal.policy.impl.PhoneWindow$PanelFeatureState$SavedState",
    };

    static {
        // For performance reasons, preload some policy specific classes when
        // the policy gets loaded.
        for (String s : preload_classes) {
            try {
                Class.forName(s);
            } catch (ClassNotFoundException ex) {
                Log.e(TAG, "Could not preload class for phone policy: " + s);
            }
        }
    }

    public Window makeNewWindow(Context context) {
        return new PhoneWindow(context);
    }

    public LayoutInflater makeNewLayoutInflater(Context context) {
        return new PhoneLayoutInflater(context);
    }

    public WindowManagerPolicy makeNewWindowManager() {
        return new PhoneWindowManager();
    }

    public FallbackEventHandler makeNewFallbackEventHandler(Context context) {
        return new PhoneFallbackEventHandler(context);
    }
}

定義產品類 (Window

代碼太多持际,咱就不貼了沃琅。

定義產品實現(xiàn)類(PhoneWindow

代碼太多,咱就不貼了蜘欲。

為什么不用4個單獨的工廠(工廠方法模式)去實現(xiàn)呢益眉?

其實四種不同的產品(Window,WindowManagerPolicy姥份,LayoutInflater郭脂,F(xiàn)allbackEventHandler),如果用四個工廠方法也是可以的澈歉,但是會缺乏將本來應該有相互關聯(lián)的產品拆分開了展鸡,抽象工廠一定程度上提高了它們之間的內聚。

假如除了Phone外闷祥,如果需要加入新的產品簇(比如說TV娱颊,智能手表),那么只需要創(chuàng)建一個對應Policy凯砍,以及對應的產品系列箱硕,然后將PolicyManager的IPolicy指向新產品簇的Policy就好了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末悟衩,一起剝皮案震驚了整個濱河市剧罩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌座泳,老刑警劉巖惠昔,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異挑势,居然都是意外死亡镇防,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進店門潮饱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來来氧,“玉大人,你說我怎么就攤上這事香拉±惭铮” “怎么了?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵凫碌,是天一觀的道長扑毡。 經常有香客問我,道長盛险,這世上最難降的妖魔是什么瞄摊? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任勋又,我火速辦了婚禮,結果婚禮上换帜,老公的妹妹穿的比我還像新娘赐写。我一直安慰自己,他們只是感情好膜赃,可當我...
    茶點故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著揉忘,像睡著了一般跳座。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上泣矛,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天疲眷,我揣著相機與錄音,去河邊找鬼您朽。 笑死狂丝,一個胖子當著我的面吹牛,可吹牛的內容都是我干的哗总。 我是一名探鬼主播几颜,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼讯屈!你這毒婦竟也來了蛋哭?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤涮母,失蹤者是張志新(化名)和其女友劉穎谆趾,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體叛本,經...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡沪蓬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了来候。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片跷叉。...
    茶點故事閱讀 38,814評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖吠勘,靈堂內的尸體忽然破棺而出性芬,到底是詐尸還是另有隱情,我是刑警寧澤剧防,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布植锉,位于F島的核電站,受9級特大地震影響峭拘,放射性物質發(fā)生泄漏俊庇。R本人自食惡果不足惜狮暑,卻給世界環(huán)境...
    茶點故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望辉饱。 院中可真熱鬧搬男,春花似錦、人聲如沸彭沼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽姓惑。三九已至褐奴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間于毙,已是汗流浹背敦冬。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留唯沮,地道東北人脖旱。 一個月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像介蛉,于是被迫代替她去往敵國和親萌庆。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,728評論 2 351

推薦閱讀更多精彩內容