當Android遇上設計模式之工廠方法(Factory)模式

設計模式六大原則:

  • 單一職責原則:就一個類僅有一個引起它變化的原因,即類承擔的職責單一性;

  • 開放封閉原則:類、模塊、函數等應該是可以擴展的,但是不可修改。換句話說,就是面對需求的改變要儘可能地保證相對穩定,儘量通過擴展的方式而不是修改原有的代碼來實現。

  • 里氏替換原則:所有引用基類(父類)的地方必須透明地使用其子類對象。換句話說,就是儘量把父類設計爲抽象類或者接口,在運行時子類實例替換父類實例,在擴展時通過增加一個新的子類實現;

  • 依賴倒置原則:高層模塊不應該依賴低層模塊,兩者都應該依賴於抽象。換句話說,就是模塊間的依賴通過抽象發生,實現類之間不發生直接依賴關係,其依賴關係是通過接口或者抽象類產生。

  • 迪米特原則:一個軟件實體應當儘可能少地與其他實體發生相互作用。換句話說,就是通過引入一個合理的第三者來降低現有對象之間的耦合度,同時在設計類時儘量降低成員的訪問權限。

  • 接口隔離原則:一個類對另一個類的依賴應該建立在最小接口上。換句話說,就是爲各個類建立專用的接口,而不要試圖建立一個龐大的接口供所有依賴它的類調用,同時接口中的方法儘量少且少用public修飾,以提高內聚和減少對外交互。

1. 簡單工廠模式

2.1 定義

 簡單工廠模式又被稱爲靜態工廠方法模式,它是創建型設計模式的一種,但不屬於23種GoF設計模式之一。學習簡單工廠模式有助於理解接下來要學習的工廠方法模式,它的定義爲:由一個工廠對象決定創建出哪一種產品類的實例。簡單工廠模式UML類圖如下:
在這裏插入圖片描述
 UML類圖角色說明:

  • Factory:工廠類,它負責創建各類產品對象,依賴於Product;
  • IProduct:抽象產品類,它負責描述所有具體產品類所共有的方法;
  • Product:具體產品類,它是Factory創建的目標,繼承於IProduct。

2.2 代碼實現

 在Android開發中,偶爾也會用到簡單工廠模式來根據不同的情況創建對應的產品對象實現特定的業務,這種模式就是實現比較簡單,避免了直接實例化類(即產品類),從而降低了耦合性。接下來,我們就以工廠生產口罩爲例來學習簡單工廠模式的實現。由於最近一段時間新型冠狀病毒的影響,人們出行不得不佩戴口罩,而並不是所有類型的口罩都能夠過濾病毒,通常只有醫用外科口罩N95型口罩可預防感染,現在我們的工廠就需要大量的生產這兩種類型的口罩。具體代碼如下:

(1)抽象產品類,IProduct

/** 抽象產品類
 * author : jiangdg
 * date   : 2020/1/30 20:00
 * desc   : 負責描述所有具體產品類所共有的方法
 * version: 1.0
 */
public abstract class Mask {
    // 產品的抽象方法,由具體的產品實現
    public abstract void efficacy();
}

(2)具體產品類,Product

  • 醫用外科口罩
/** 具體產品
 * author : jiangdg
 * date   : 2020/1/30 20:00
 * desc   : 醫用外科口罩
 * version: 1.0
 */
public class SurgicalMask extends Mask{
    @override
    public void efficacy() {
        Log.d("debug", "預防呼吸道感染");
    }
}
  • N95型口罩
/** 具體產品
 * author : jiangdg
 * date   : 2020/1/30 20:00
 * desc   : N95型口罩
 * version: 1.0
 */
public class N95Mask extends Mask{
    @override
    public void efficacy() {
        Log.d("debug", "預防呼吸道感染、防霧霾");
    }
}

(3)工廠類,Factory

/** 工廠類
 * author : jiangdg
 * date   : 2020/1/30 20:00
 * desc   : 創建指定的產品
 * version: 1.0
 */
public class MaskFactory {
    // 創建具體的產品
    public static Mask createMask(String type) {
        Mask mask = null;
        switch(type) {
            case "n95":
                mask = new N95Mask();
                break;
            case "surgical":
                mask = new SurgicalMask();
                break;
        }
        return mask;
    }
}

 工廠類MaskFactory提供了一個靜態方法createMask用來生成不同類型的口罩,我們只需要向其傳入表示某種口罩的標誌,它就會實例化相應的口罩產品對象。客戶端調用工廠類方式:

// 創建醫用外科口罩產品實例
Mask surgicalMask = MaskFactory.createMask("surgical");
surgicalMask.efficacy();
// 創建N95口罩產品實例
Mask n95Mask = MaskFactory.createMask("n95");
n95Mask.efficacy();

2.3 使用場景

  • 工廠類負責常見的"產品"對象比較少,且工廠類功能穩定,不需要擴展;
  • 客戶端只需傳入工廠類的參數就能獲得對應的產品對象,而無需關心創建對象的具體邏輯。

 前面說到,簡單工廠模式實現較爲簡單,避免了直接實例化類,從而達到了降低耦合性的目的,但是,當遇到需要添加新的產品類型時,比如上例中我們的工廠需要再生產一種活性炭口罩(用於吸附空氣中的污染物)時,就不得不修改工廠類MaskFactory,以添加一個case判斷,這就違背了開放-封閉原則。此外,如果工廠需要生產的口罩種類非常之多,這就會導致createMask方法非常臃腫。爲了最大程度的解耦和使程序更具擴展性,工廠方法模式便閃亮登場。

2. 工廠方法模式

2.1 定義

 工廠方法模式是創建型設計模式的一種,它的定義爲:定義一個用於創建對象的接口,讓子類決定實例化哪個類。換句話來說,就是工廠方法使一個類的實例化延遲到其子類。工廠方法模式UML類圖如下:
在這裏插入圖片描述
 從上述類圖可知,工廠方法模式對比於簡單工廠模式,它把工廠類進一步抽象化,這就使得我們可以根據不同的產品由對應的具體工廠類來創建。UML類圖中角色說明:

  • IProduct:抽象產品類,同簡單工廠模式;

  • Product:具體產品類,實現IProduct,同簡單工廠模式;

  • Factory:抽象工廠類,該方法返回一個IProduct類型的對象;

  • ConcreteFactory:具體工廠類,返回Product實例;

2.2 代碼實現

 關於工廠方法模式的代碼實現,這裏仍以製造口罩爲例,IProduct和Product類的實現同簡單工廠模式,接下來,我們看下Factory和ConcreteFactory兩種類的實現。

(1)抽象工廠類,Factory

/** 抽象工廠類
 * author : jiangdg
 * date   : 2020/1/30 20:00
 * desc   : 提供具體工廠類公共方法
 * version: 1.0
 */
public abstract class Factory {
    public abstract IProduct createProduct();
}

(2)具體工廠類,ConcreteFactory

  • 專門製造醫用外科口罩的工廠
/** 製造醫用外科口罩工廠
 * author : jiangdg
 * date   : 2020/1/30 20:00
 * desc   : 
 * version: 1.0
 */
public class SurgicalMaskFactory {
    @Override
    public IProduct createProduct() {
        return new SurgicalMask();
    }
}
  • 專門製造N95型口罩的工廠
/** 製造N95型口罩工廠
 * author : jiangdg
 * date   : 2020/1/30 20:00
 * desc   : 
 * version: 1.0
 */
public class N95MaskFactory {
    @Override
    public IProduct createProduct() {
        return new N95Mask();
    }
}

 從上面代碼可知,我們將每個產品的創建分別交給對應的具體工廠類即可,也就是說,每個具體的工廠類只負責某種類型口罩的生產,這就符合了設計模式中的開放-封閉原則。假如我們需要新增一款活性炭口罩,就只需要新增一個具體的產品類carbonMask和具體工廠類carbonMaskFactory即可,這也符合了設計模式中的單一職責原則。客戶端創建產品對象方法:

// 創建醫用外科口罩
Factory surgicalFactory = new SurgicalMaskFactory();
SurgicalMask mask = surgicalFactory.createProduct();
// 創建N95口罩
Factory n95Factory = new N95MaskFactory();
N96Mask mask = n95Factory.createProduct();

2.3 使用場景

 工廠方法模式可以說是簡單工廠模式的進一步抽象和擴展,它保留了簡單工廠模式的封裝優點的同時,讓擴展變得簡單,更加符合設計模式中的開放-封閉原則單一職責原則,是多態性的重要體現。雖然它的優點很明顯,但是缺點也是有的,比如每次添加一個新產品,除了要新增新產品類外,還需要新增與之對應的具體工廠類,這就會導致隨着產品的個數的增加,相應的類也會增加。另外,就是一個具體工廠類只能創建一種具體的產品,這貌似有點浪費。根據工廠方式模式的優缺點,它的常見應用場景爲:

  • 當一個類不知道它所需要的對象的類時,只知道其所對應的工廠即可;

  • 當一個類希望通過其子類來指定創建對象時,以使得程序更具擴展性;

文章的最後,希望國家能夠早日攻克新型冠狀病毒,受感染的同胞們早日康復,武漢加油!中國加油!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章