爲什麼工廠模式是華而不實的—淺談工廠模式的利與弊


轉載請註明出處:http://blog.csdn.net/singwhatiwanna/article/details/17428923

說明:博主虛心接受大家的抨擊,批評,指正

前言
我一直想介紹下工廠模式,我曾經搞過J2EE,用的是輕量級SSH框架,其中Spring有IOC概念,可以稱之爲控制反轉或者依賴注入,在系統開發中,IOC可以很好的替代工廠模式。若干年前,我只用過IOC,並沒有用過工廠模式,但是工廠模式這個概念卻是給我留下了深深的印象,畢竟,它是我所聽說過第一個設計模式,我想它應該是很強大的吧。但是,事情不是我想的那個樣子的,在我之前所參與的項目(Android)中幾乎沒有工廠模式的身影,僅僅是有一個項目採用了簡單工廠模式去管理所有的業務管理器。後來,我開始仔細研究工廠模式,發現工廠模式是讓我失望的。工廠模式有三種實現方式:簡單工廠、工廠方法和抽象廣場,除了簡單工廠我還發現了一點使用價值外,後兩者我基本沒發現有啥可使用價值。也許我的理解還不夠透徹,但是目前網上存在的大部分介紹工廠模式的文章都體現了一點:華而不實,難以實際應用。一篇文章不能清晰的介紹一個概念,不能清晰的說明爲什麼要使用這個東西以及如何使用這個東西,那麼這篇文章不算好文章的。我目前所看到的關於工廠模式的介紹都是不充分的,包括我寫的這篇,期待真正的好文章出現。下面將介紹簡單工廠模式以及一個實際項目中使用的例子,後面我將會簡單闡述我的觀點:爲什麼工廠模式是華而不實的。

簡單工廠模式
1.爲什麼要使用工廠模式
直接目的:避免在代碼中出現大量的new關鍵字

根本目的:將對象的創建統一起來便於維護和整體把控

這一點可以理解,加入你在項目中new了某個對象100次,一年後由於業務邏輯變更,構造方法多了一個參數,你會怎麼辦?你應該會這麼做:找到這100個對象new的地方,用新的構造方法來創建對象,你重複勞動了100次,假如採用工廠模式,你只用改一次:把創建工廠給改一下就好了。這就是工廠模式最簡單最直接的好處。

2.工廠模式的示例
下面是最常見的一個示範,其實它的原理就是面向對象中的多態+接口編程,雖然返回的都是Car類型,但是drive的時候會調用真正的實例中的對應方法。按照抽象類和接口的意義歸屬,Car應該被定義成抽象類,因爲Benz、Bmw和Car的關係是繼承關係,而接口表示的一組行爲。但是,爲什麼這裏還要定義成接口,是因爲Java和.NET不支持多繼承,如果繼承了Car,就無法繼承其他類,有時候業務需要必須繼承其他類,這個時候代碼就不能用了。當然,C++中支持多繼承,因此可以在C++中使用抽象類,另外C++沒接口的概念,但你可以模擬接口。這裏只介紹簡單工廠模式,至於剩下兩種工廠模式,我覺得更沒有使用價值。

interface Car {
    void drive();
}
 
class Benz implements Car {
 
    @Override
    public void drive() {
        System.out.println("drive Benz");
    }
 
}
 
class Bmw implements Car {
 
    @Override
    public void drive() {
        System.out.println("drive Bmw");
    }
 
}
 
class CarFactory {
    public static Car creator(String carType) {
        if (carType.equals("Benz")) {
            return new Benz();
        } else if (carType.equals("Bmw")) {
            return new Bmw();
        } else {
            throw new UnsupportedOperationException("car with type" + carType
                    + " is not supported.");
        }
    }
}
 
public class A {
    public static void main(String args[]) {
        Car benz = CarFactory.creator("Benz");
        benz.drive();
        Car bmw = CarFactory.creator("Bmw");
        bmw.drive();
    }
}
上述代碼是沒啥用的,看一個實際使用的例子。下面這個工廠模式的意義在於能夠統一管理所有的業務管理器,僅此而已。

/**
 * 管理器的工程,初始化所有業務的管理器
 */
public class ManagerFactory {
    // 緩存管理器實例的集合
    private transient Map<Byte, IManager> mManagerMap = null;
 
    private static ManagerFactory sIntance = new ManagerFactory();
 
    private ManagerFactory() {
        mManagerMap = new HashMap<Byte, IManager>();
    }
 
    public ManagerFactory getInstance() {
        return sInstance;
    }
 
    /**
     * 獲取管理器實例
     * 
     * @param context  上下文
     * @param id  管理器ID
     * @return  管理器實例
     */
    protected IManager getManager(final Context context, final byte id) {
        IManager manager = mManagerMap.get(mId);
 
        if (manager == null) {
            switch (id) {
            case DB_ID:
                manager = new DBManager(context);
                break;
            case DOWNLOAD_ID:
                manager = new DownloadManager(context);
                break;
            case NETWORK_ID:
                manager = new NetworkManager();
                break;
            case IMAGE_ID:
                manager = new ImageManager();
                break;
            default:
                break;
            }
            mManagerMap.put(id, manager);
        }
 
        return manager;
    }
}
工廠模式爲什麼沒有太大價值
1.有利有弊
優點:將對象的創建統一起來便於維護和整體把控,對擴展開放,對修改封閉

缺點:耦合性提高,由於工廠類集中了所有實例的創建邏輯,違反了高內聚責任分配原則,將全部創建邏輯集中到了一個工廠類中,這種對條件的判斷和對具體產品類型的判斷交錯在一起,很難避免模塊功能的蔓延,對系統的維護和擴展非常不利。

2.使用有限制
從工廠模式的示例可以看出:工廠模式需要類實現它的接口並且在業務內部存在明顯的繼承關係,比如汽車和奔馳寶馬的關係。而繼承關係往往存在於模型之間,業務之間很難存在繼承關係,因此如果業務內部或者業務之間沒有這種顯式的繼承關係該咋辦?就算業務內部有繼承關係,各個業務交給你統一管理,這樣就會提高代碼的耦合性,當創建邏輯複雜的時候,工廠方法就很複雜,容易產生干擾。

3.其開閉性優點很容易被替代
可以通過高度層次化和模塊化來提高系統的開閉性,而不必生硬地去套用工廠模式。
————————————————
版權聲明:本文爲CSDN博主「singwhatiwanna」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/singwhatiwanna/java/article/details/17428923

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