設計模式------工廠方法模式

AbstractHumanFactory是一個抽象類,定義了一個八卦爐都具有的整體功能,

 HumanFactory爲實現類,完成具體的任務:創建人類;

 Human接口是人類的總稱,其三個實現類分別爲三類人種;

 NvWa類是一個場景類,負責模擬這個場景,執行相關的任務。

我們定義的每個人種都有兩個方法:getColor(獲得人的皮膚顏色)和talk(交談),其源代碼如代碼清單1所示。


代碼清單1 人類總稱

public interface Human {

    // 每個人種皮膚都有相應的顏色

    public void getColor();

    // 人類會說話

    public void talk();

}

接口Human是對人類的總稱,每個人種都至少具有兩個方法,黑色人種、***人種、白色人種的代碼分別如代碼清單2、3、4所示。


代碼清單2 黑色人種

public class BlackHuman implements Human {

    @Override

    public void getColor() {

        System.out.println("黑種人的皮膚顏色是黑色的!");

    }

    @Override

    public void talk() {

        System.out.println("黑人會說話,一般聽不懂。");

    }

}

代碼清單3 ***人種

public class YellowHuman implements Human {

    @Override

    public void getColor() {

        System.out.println("黃種人的皮膚顏色是***的!");

    }

    @Override

    public void talk() {

        System.out.println("黃種人會說話,一般說的都是雙字節。");

    }

}

代碼清單4 白色人種

public class WhiteHuman implements Human {

    @Override

    public void getColor() {

        System.out.println("白種人的皮膚顏色是白色的!");

    }

    @Override

    public void talk() {

        System.out.println("白種人會說話,一般都是單字節。");

    }

}

所有的人種定義完畢,下一步就是定義一個八卦爐,然後燒製人類。我們想象一下,女媧最可能給八卦爐下達什麼樣的生產命令呢?應該是“給我生產出一個***人種(YellowHuman類)”,而不會是“給我生產一個會走、會跑、會說話、皮膚是***的人種”,因爲這樣的命令增加了交流的成本,作爲一個生產的管理者,只要知道生產什麼就可以了,而不需要事物的具體信息。通過分析,我們發現八卦爐生產人類的方法輸入參數類型應該是Human接口的實現類,這也解釋了爲什麼類圖上的AbstractHumanFactory抽象類中createHuman方法的參數爲Class類型。其源代碼如代碼清單5所示。


代碼清單5 抽象人類創建工廠

public abstract class AbstractHumanFactory {

    public abstract Human createHuman(Class<? extends Human> clazz);

}

注意,我們在這裏採用了JDK 1.5的新特性:泛型(Generic),通過定義泛型對createHuman的輸入參數產生兩層限制:


必須是Class類型;

必須是Human的實現類;

其中的“?”表示的是,只要實現了Human接口的類都可以作爲參數,泛型是JDK 1.5中的一個非常重要的新特性,它減少了對象間的轉換,約束其輸入參數類型,對Collection集合下的實現類都可以定義泛型。有關泛型詳細知識,請參考相關的Java語法文檔。


目前女媧只有一個八卦爐,其實現了生產人類的方法,如代碼清單6所示。


代碼清單6 人類創建工廠

public class HumanFactory extends AbstractHumanFactory {

    @Override

    public Human createHuman(Class<? extends Human> clazz) {

        // 定義一個生產的人種

        Human human = null;

        try {

            human = (Human) Class.forName(clazz.getName()).newInstance();

        } catch (Exception e) {

            System.out.println("人種生成錯誤!");

        }

        return human;

    }

}

人種有了,八卦爐也有了,剩下的工作就是女媧採集黃土,然後命令八卦爐開始生產,其過程如代碼清單7所示。


代碼清單7 女媧類

public class NvWa {

    public static void main(String[] args) {

        // 聲明陰陽八卦爐

        AbstractHumanFactory YinYangLu = new HumanFactory();

                                                                                                    

        // 女媧第一次造人,火候不足,缺陷產品

        System.out.println("--造出的第一批人是白色人種--");

        Human whiteHuman = YinYangLu.createHuman(WhiteHuman.class);

        whiteHuman.getColor();

        whiteHuman.talk();

                                                                                                    

        // 女媧第二次造人,火候過足,又是次品,

        System.out.println("\n--造出的第二批人是黑色人種--");

        Human blackHuman = YinYangLu.createHuman(BlackHuman.class);

        blackHuman.getColor();

        blackHuman.talk();

        // 第三次造人,火候剛剛好,優品!***人種

        System.out.println("\n--造出的第三批人是***人種--");

        Human yellowHuman = YinYangLu.createHuman(YellowHuman.class);

        yellowHuman.getColor();

        yellowHuman.talk();

    }

}

人種有了,八卦爐有了,負責生產的女媧也有了,激動人心的時刻到來了,我們運行一下,結果如下所示。


--造出的第一批人是白色人種--


白色人種的皮膚顏色是白色的!


白色人種會說話,一般都是但是單字節。


--造出的第二批人是黑色人種--


黑色人種的皮膚顏色是黑色的!


黑人會說話,一般人聽不懂。


--造出的第三批人是***人種--


***人種的皮膚顏色是***的!


***人種會說話,一般說的都是雙字節。


哇,人類的生產過程就展現出來了!這個世界就熱鬧起來了,黑人、白人、黃人都開始活動了,這也正是我們現在的真實世界。以上就是工廠方法模式(沒錯,對該部分有疑問,請繼續閱讀下去)。




工廠方法模式的定義

工廠方法模式使用的頻率非常高,在我們日常的開發中總能見到它的身影。其定義爲:


Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses。定義一個用於創建對象的接口,讓子類決定實例化哪一個類。工廠方法使一個類的實例化延遲到其子類。


工廠方法模式的通用類圖如圖2所示。


圖2 工廠方法模式通用類圖


在工廠方法模式中,


抽象產品類Product負責定義產品的共性,實現對事物最抽象定義;


Creator爲抽象創建類,也就是抽象工廠,具體如何創建產品類是由具體的實現工廠ConcreteCreator完成的。


工廠方法模式的變種較多,我們來看一個比較實用的通用源碼。




抽象產品類代碼如代碼清單8所示。


代碼清單8 抽象產品類

public abstract class Product {

    // 產品類的公共方法

    public void method1() {

        // 業務邏輯處理

    }

    // 抽象方法

    public abstract void method2();

}



具體的產品類可以有多個,都繼承於抽象產品類,其源代碼如代碼清單9所示。


代碼清單9 具體產品類

public class ConcreteProduct1 extends Product {

    @Override

    public void method2() {

        // 業務邏輯處理

    }

}

public class ConcreteProduct2 extends Product {

    @Override

    public void method2() {

        // 業務邏輯處理

    }

}

抽象工廠類負責定義產品對象的產生,源代碼如代碼清單10所示。


代碼清單10 抽象工廠類

public abstract class Creator {

    /**

     * 創建一個產品對象,其輸入參數類型可以自行設置 通常爲String、Enum、Class等,當然也可以爲空

     *

     * @param clazz

     * @return

     */

    public abstract Product createProduct(Class<? extends Product> clazz);

}

具體如何產生一個產品的對象,是由具體的工廠類實現的,如代碼清單11所示。


代碼清單11 具體工廠類

public class ConcreteCreator extends Creator {

    @Override

    public Product createProduct(Class<? extends Product> clazz) {

        Product product = null;

        try {

            product = (Product) Class.forName(clazz.getName()).newInstance();

        } catch (Exception e) {

            // 異常處理

        }

        return product;

    }

}

場景類的調用方法如代碼清單12所示。


代碼清單12 場景類

public class Client {

    public static void main(String[] args) {

        Creator creator = new ConcreteCreator();

        Product product = creator.createProduct(ConcreteProduct1.class);

        /*

        * 繼續業務處理

        */

    }

}

  該通用代碼是一個比較實用、易擴展的框架,讀者可以根據實際項目需要進行擴展。

工廠方法模式的擴展

縮小爲簡單工廠模式

    我們這樣考慮一個問題:一個模塊僅需要一個工廠類,沒有必要把它產生出來,使用靜態的方法就可以了,根據這一要求,我們把上例中的AbstarctHumanFactory修改一下,

最佳實踐

工廠方法模式在項目中使用得非常頻繁,以至於很多代碼中都包含工廠方法模式。該模式幾乎盡人皆知,但不是每個人都能用得好。熟能生巧,熟練掌握該模式,多思考工廠方法如何應用,而且工廠方法模式還可以與其他模式混合使用(例如模版方法模式、單例模式、原型模式等),變化出無窮的優秀設計,這也正是軟件設計和開發的樂趣所在。



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