天天看點

工廠方法設計模式

一、例舉

物美超市搞促銷活動,促銷活動有很多:買二贈一、滿3件8折、滿100減10等,一般的設計思路是:給每種促銷活動寫一個計算類,再寫一個簡單工廠來生産各種促銷算法類來解耦用戶端與活動實作類,例如:

// 活動
public interface Activity {
    float calculate(float money);
}

// 滿減
public class ManJian implements {
    public float calculate(float money) {
        // 滿減金額計算
    }
}

// 打折
public class Discount implements {
    public float calculate(float money) {
        // 折扣金額計算
    }
}

public class SaleFactory {
    public Activity getSaleActivity(String sale) {
        switch(sale) {
            case "滿減":
                return new ManJian();
                break;
            case "折扣":
                return new Discount();
                break;
        }
    }
}
           

以上這種方法也是比較常用的一種方法,但是有個問題,如果新添加一種促銷活動,比如來個“買一贈一”怎麼辦,你會說在swich中再加一個case呗,再來一個呢,再來一個呢,再。。。。來一個,一直在裡面加,有沒有感覺這樣有什麼不好,說好的“對修改封閉,對擴充開放”呢? 那我們怎樣修改呢,那我們可不可以找一種可以不用修改之前的類,隻通過擴充來進行建立的方式呢,嘗試一下:

// 活動
public interface Activity {
    float calculate(float money);
}

// 滿減
public class ManJian implements {
    public float calculate(float money) {
        // 滿減金額計算
    }
}

// 打折
public class Discount implements {
    public float calculate(float money) {
        // 折扣金額計算
    }
}

// 促銷抽象工廠
public abstract class Factory {
    protected abstract Activity factoryMethod();

    public Activity getActivity() {
        return factoryMethod();
    }
}

// 滿減促銷工廠
public class ManJianFactory {
    protecte Activity factoryMethod() {
        return new ManJian();
    }
}

// 折扣促銷工廠
public class DiscountFactory {
    protecte Activity factoryMethod() {
        return new Discount();
    }
}

// 用戶端
public class Client {
    public static void main() {
        float money = ;
        Factory factory = new DiscountFactory();
        Activity activity = factory.getActivity();
        float result = activity.calcute();
    }
}
           

該實作方法就是“工廠方法設計模式”。

二、用來解決的問題

工廠方法解決的問題是針對簡單工廠來說的,簡單工廠一旦需要生産新産品就需要修改工廠類的方法邏輯,違背了“開放封裝原則”,而工廠方法模式把具體産品的建立推遲到具體工廠中,此時工廠類不再負責所有産品的建立,而隻是給出具體工廠必須實作的接口,這樣真正做到了“對擴充開放,對修改封閉”。

三、定義

定義一個用于建立對象的接口,讓子類決定執行個體化哪一個類,工場方法使一個類的執行個體化延遲到其子類。

四、UML說明

工廠方法設計模式
  • Product:抽象産品
  • ConcreateProduct:具體産品
  • Creator:抽象工廠方法,用來傳回具體的産品
  • ConcreteCreator:具體工廠方法

五、使用場景

  • 如果一個類需要建立某個接口對象,但是又不知道具體的的實作,這種情況可以選用工廠方法,将建立對象的工作延遲到子類。
  • 如果一個類本身就希望由它的子類來建立所需要的對象的時候,應該使用工廠方法。

六、優缺點對比(與簡單工廠對比)

優點

  • 更符合開-閉原則:增加一個新産品時不用修改之前工廠的判斷邏輯。
  • 更符合單一職責:簡單工廠中的建立方法存在複制的switch判斷

缺點

每添加一個産品,除了要建立産品類還要多建立一個工廠實作類,類的個數增加,一定程式上增加了系統複雜度,而且會有更多的類需要編譯運作,增加編譯成本。

繼續閱讀