# 工廠三兄弟之抽象工廠模式(五)
5 “開閉原則”的傾斜性
Sunny公司使用抽象工廠模式設計了界面皮膚庫,該皮膚庫可以較為方便地增加新的皮膚,但是現在遇到一個非常嚴重的問題:由于設計時考慮不全面,忘記為單選按鈕(RadioButton)提供不同皮膚的風格化顯示,導致無論選擇哪種皮膚,單選按鈕都顯得那么“格格不入”。Sunny公司的設計人員決定向系統中增加單選按鈕,但是發現原有系統居然不能夠在符合“開閉原則”的前提下增加新的組件,原因是抽象工廠SkinFactory中根本沒有提供創建單選按鈕的方法,如果需要增加單選按鈕,首先需要修改抽象工廠接口SkinFactory,在其中新增聲明創建單選按鈕的方法,然后逐個修改具體工廠類,增加相應方法以實現在不同的皮膚中創建單選按鈕,此外還需要修改客戶端,否則單選按鈕無法應用于現有系統。
怎么辦?答案是抽象工廠模式無法解決該問題,這也是抽象工廠模式最大的缺點。在抽象工廠模式中,增加新的產品族很方便,但是增加新的產品等級結構很麻煩,抽象工廠模式的這種性質稱為“開閉原則”的傾斜性。“開閉原則”要求系統對擴展開放,對修改封閉,通過擴展達到增強其功能的目的,對于涉及到多個產品族與多個產品等級結構的系統,其功能增強包括兩方面:
(1) 增加產品族:對于增加新的產品族,抽象工廠模式很好地支持了“開閉原則”,只需要增加具體產品并對應增加一個新的具體工廠,對已有代碼無須做任何修改。
(2) 增加新的產品等級結構:對于增加新的產品等級結構,需要修改所有的工廠角色,包括抽象工廠類,在所有的工廠類中都需要增加生產新產品的方法,違背了“開閉原則”。
正因為抽象工廠模式存在“開閉原則”的傾斜性,它以一種傾斜的方式來滿足“開閉原則”,為增加新產品族提供方便,但不能為增加新產品結構提供這樣的方便,因此要求設計人員在設計之初就能夠全面考慮,不會在設計完成之后向系統中增加新的產品等級結構,也不會刪除已有的產品等級結構,否則將會導致系統出現較大的修改,為后續維護工作帶來諸多麻煩。
6 抽象工廠模式總結
抽象工廠模式是工廠方法模式的進一步延伸,由于它提供了功能更為強大的工廠類并且具備較好的可擴展性,在軟件開發中得以廣泛應用,尤其是在一些框架和API類庫的設計中,例如在Java語言的AWT(抽象窗口工具包)中就使用了抽象工廠模式,它使用抽象工廠模式來實現在不同的操作系統中應用程序呈現與所在操作系統一致的外觀界面。抽象工廠模式也是在軟件開發中最常用的設計模式之一。
1. 主要優點
抽象工廠模式的主要優點如下:
(1) 抽象工廠模式隔離了具體類的生成,使得客戶并不需要知道什么被創建。由于這種隔離,更換一個具體工廠就變得相對容易,所有的具體工廠都實現了抽象工廠中定義的那些公共接口,因此只需改變具體工廠的實例,就可以在某種程度上改變整個軟件系統的行為。
(2) 當一個產品族中的多個對象被設計成一起工作時,它能夠保證客戶端始終只使用同一個產品族中的對象。
(3) 增加新的產品族很方便,無須修改已有系統,符合“開閉原則”。
2. 主要缺點
抽象工廠模式的主要缺點如下:
增加新的產品等級結構麻煩,需要對原有系統進行較大的修改,甚至需要修改抽象層代碼,這顯然會帶來較大的不便,違背了“開閉原則”。
3. 適用場景
在以下情況下可以考慮使用抽象工廠模式:
(1) 一個系統不應當依賴于產品類實例如何被創建、組合和表達的細節,這對于所有類型的工廠模式都是很重要的,用戶無須關心對象的創建過程,將對象的創建和使用解耦。
(2) 系統中有多于一個的產品族,而每次只使用其中某一產品族。可以通過配置文件等方式來使得用戶可以動態改變產品族,也可以很方便地增加新的產品族。
(3) 屬于同一個產品族的產品將在一起使用,這一約束必須在系統的設計中體現出來。同一個產品族中的產品可以是沒有任何關系的對象,但是它們都具有一些共同的約束,如同一操作系統下的按鈕和文本框,按鈕與文本框之間沒有直接關系,但它們都是屬于某一操作系統的,此時具有一個共同的約束條件:操作系統的類型。
(4) 產品等級結構穩定,設計完成之后,不會向系統中增加新的產品等級結構或者刪除已有的產品等級結構。
練習
> Sunny軟件公司欲推出一款新的手機游戲軟件,該軟件能夠支持Symbian、Android和Windows Mobile等多個智能手機操作系統平臺,針對不同的手機操作系統,該游戲軟件提供了不同的游戲操作控制(OperationController)類和游戲界面控制(InterfaceController)類,并提供相應的工廠類來封裝這些類的初始化過程。軟件要求具有較好的擴展性以支持新的操作系統平臺,為了滿足上述需求,試采用抽象工廠模式對其進行設計。
- Introduction
- 基礎知識
- 設計模式概述
- 從招式與內功談起——設計模式概述(一)
- 從招式與內功談起——設計模式概述(二)
- 從招式與內功談起——設計模式概述(三)
- 面向對象設計原則
- 面向對象設計原則之單一職責原則
- 面向對象設計原則之開閉原則
- 面向對象設計原則之里氏代換原則
- 面向對象設計原則之依賴倒轉原則
- 面向對象設計原則之接口隔離原則
- 面向對象設計原則之合成復用原則
- 面向對象設計原則之迪米特法則
- 六個創建型模式
- 簡單工廠模式-Simple Factory Pattern
- 工廠三兄弟之簡單工廠模式(一)
- 工廠三兄弟之簡單工廠模式(二)
- 工廠三兄弟之簡單工廠模式(三)
- 工廠三兄弟之簡單工廠模式(四)
- 工廠方法模式-Factory Method Pattern
- 工廠三兄弟之工廠方法模式(一)
- 工廠三兄弟之工廠方法模式(二)
- 工廠三兄弟之工廠方法模式(三)
- 工廠三兄弟之工廠方法模式(四)
- 抽象工廠模式-Abstract Factory Pattern
- 工廠三兄弟之抽象工廠模式(一)
- 工廠三兄弟之抽象工廠模式(二)
- 工廠三兄弟之抽象工廠模式(三)
- 工廠三兄弟之抽象工廠模式(四)
- 工廠三兄弟之抽象工廠模式(五)
- 單例模式-Singleton Pattern
- 確保對象的唯一性——單例模式 (一)
- 確保對象的唯一性——單例模式 (二)
- 確保對象的唯一性——單例模式 (三)
- 確保對象的唯一性——單例模式 (四)
- 確保對象的唯一性——單例模式 (五)
- 原型模式-Prototype Pattern
- 對象的克隆——原型模式(一)
- 對象的克隆——原型模式(二)
- 對象的克隆——原型模式(三)
- 對象的克隆——原型模式(四)
- 建造者模式-Builder Pattern
- 復雜對象的組裝與創建——建造者模式(一)
- 復雜對象的組裝與創建——建造者模式(二)
- 復雜對象的組裝與創建——建造者模式(三)
- 七個結構型模式
- 適配器模式-Adapter Pattern
- 不兼容結構的協調——適配器模式(一)
- 不兼容結構的協調——適配器模式(二)
- 不兼容結構的協調——適配器模式(三)
- 不兼容結構的協調——適配器模式(四)
- 橋接模式-Bridge Pattern
- 處理多維度變化——橋接模式(一)
- 處理多維度變化——橋接模式(二)
- 處理多維度變化——橋接模式(三)
- 處理多維度變化——橋接模式(四)
- 組合模式-Composite Pattern
- 樹形結構的處理——組合模式(一)
- 樹形結構的處理——組合模式(二)
- 樹形結構的處理——組合模式(三)
- 樹形結構的處理——組合模式(四)
- 樹形結構的處理——組合模式(五)
- 裝飾模式-Decorator Pattern
- 擴展系統功能——裝飾模式(一)
- 擴展系統功能——裝飾模式(二)
- 擴展系統功能——裝飾模式(三)
- 擴展系統功能——裝飾模式(四)
- 外觀模式-Facade Pattern
- 深入淺出外觀模式(一)
- 深入淺出外觀模式(二)
- 深入淺出外觀模式(三)
- 享元模式-Flyweight Pattern
- 實現對象的復用——享元模式(一)
- 實現對象的復用——享元模式(二)
- 實現對象的復用——享元模式(三)
- 實現對象的復用——享元模式(四)
- 實現對象的復用——享元模式(五)
- 代理模式-Proxy Pattern
- 設計模式之代理模式(一)
- 設計模式之代理模式(二)
- 設計模式之代理模式(三)
- 設計模式之代理模式(四)
- 十一個行為型模式
- 職責鏈模式-Chain of Responsibility Pattern
- 請求的鏈式處理——職責鏈模式(一)
- 請求的鏈式處理——職責鏈模式(二)
- 請求的鏈式處理——職責鏈模式(三)
- 請求的鏈式處理——職責鏈模式(四)
- 命令模式-Command Pattern
- 請求發送者與接收者解耦——命令模式(一)
- 請求發送者與接收者解耦——命令模式(二)
- 請求發送者與接收者解耦——命令模式(三)
- 請求發送者與接收者解耦——命令模式(四)
- 請求發送者與接收者解耦——命令模式(五)
- 請求發送者與接收者解耦——命令模式(六)
- 解釋器模式-Interpreter Pattern
- 自定義語言的實現——解釋器模式(一)
- 自定義語言的實現——解釋器模式(二)
- 自定義語言的實現——解釋器模式(三)
- 自定義語言的實現——解釋器模式(四)
- 自定義語言的實現——解釋器模式(五)
- 自定義語言的實現——解釋器模式(六)
- 迭代器模式-Iterator Pattern
- 遍歷聚合對象中的元素——迭代器模式(一)
- 遍歷聚合對象中的元素——迭代器模式(二)
- 遍歷聚合對象中的元素——迭代器模式(三)
- 遍歷聚合對象中的元素——迭代器模式(四)
- 遍歷聚合對象中的元素——迭代器模式(五)
- 遍歷聚合對象中的元素——迭代器模式(六)
- 中介者模式-Mediator Pattern
- 協調多個對象之間的交互——中介者模式(一)
- 協調多個對象之間的交互——中介者模式(二)
- 協調多個對象之間的交互——中介者模式(三)
- 協調多個對象之間的交互——中介者模式(四)
- 協調多個對象之間的交互——中介者模式(五)
- 備忘錄模式-Memento Pattern
- 撤銷功能的實現——備忘錄模式(一)
- 撤銷功能的實現——備忘錄模式(二)
- 撤銷功能的實現——備忘錄模式(三)
- 撤銷功能的實現——備忘錄模式(四)
- 撤銷功能的實現——備忘錄模式(五)
- 觀察者模式-Observer Pattern
- 對象間的聯動——觀察者模式(一)
- 對象間的聯動——觀察者模式(二)
- 對象間的聯動——觀察者模式(三)
- 對象間的聯動——觀察者模式(四)
- 對象間的聯動——觀察者模式(五)
- 對象間的聯動——觀察者模式(六)
- 狀態模式-State Pattern
- 處理對象的多種狀態及其相互轉換——狀態模式(一)
- 處理對象的多種狀態及其相互轉換——狀態模式(二)
- 處理對象的多種狀態及其相互轉換——狀態模式(三)
- 處理對象的多種狀態及其相互轉換——狀態模式(四)
- 處理對象的多種狀態及其相互轉換——狀態模式(五)
- 處理對象的多種狀態及其相互轉換——狀態模式(六)
- 策略模式-Strategy Pattern
- 算法的封裝與切換——策略模式(一)
- 算法的封裝與切換——策略模式(二)
- 算法的封裝與切換——策略模式(三)
- 算法的封裝與切換——策略模式(四)
- 模板方法模式-Template Method Pattern
- 模板方法模式深度解析(一)
- 模板方法模式深度解析(二)
- 模板方法模式深度解析(三)
- 訪問者模式-Visitor Pattern
- 操作復雜對象結構——訪問者模式(一)
- 操作復雜對象結構——訪問者模式(二)
- 操作復雜對象結構——訪問者模式(三)
- 操作復雜對象結構——訪問者模式(四)
- 設計模式趣味學習(復習)
- 設計模式與足球(一)
- 設計模式與足球(二)
- 設計模式與足球(三)
- 設計模式與足球(四)
- 設計模式綜合應用實例
- 多人聯機射擊游戲
- 多人聯機射擊游戲中的設計模式應用(一)
- 多人聯機射擊游戲中的設計模式應用(二)
- 數據庫同步系統
- 設計模式綜合實例分析之數據庫同步系統(一)
- 設計模式綜合實例分析之數據庫同步系統(二)
- 設計模式綜合實例分析之數據庫同步系統(三)