工廠方法模式

在上一篇文章中工廠模式——簡單工廠模式 我們了解到簡單工廠模式的運用和存在的問題。

回顧下簡單工廠模式里的工廠類寫法:

/**
 * 工廠類
 *
 * @author jinzifu
 * @create 2018/2/23 14:41
 */
public class FoodFactory {

    /**
     * 工廠類靜態(tài)方法
     * @param type  產(chǎn)品類型參數(shù)
     * @return
     */
    public static IMakeFood getInstance(String type) {
        IMakeFood iMakeFood = null;
        if (type.equalsIgnoreCase("Breakfest")) {
            iMakeFood = new Breakfest();
        } else if (type.equalsIgnoreCase("Lunch")) {
            iMakeFood = new Lunch();
        }
        return iMakeFood;
    }
}

如果新增了一個產(chǎn)品對象,如晚飯。工廠類靜態(tài)方法內(nèi)須增加"else if"方可,這就違背了“開閉原則”,同時也存在如下問題。

  • 簡單工廠模式實現(xiàn)了對象的“創(chuàng)建”和“使用”的分離,遵循了“單一職責(zé)原則”,但增加新的產(chǎn)品對象時須修改工廠類靜態(tài)方法,違背了“開閉原則”。
  • 工廠類集中了所有產(chǎn)品創(chuàng)建邏輯(幾乎是全能的),一旦不能工作,整個系統(tǒng)影響很大。
  • 工廠類中使用了靜態(tài)工廠方法,造成該類方法無法形成基于繼承的等級結(jié)構(gòu)。

工廠方法模式角色分工

工廠方法模式有四部分組成:抽象工廠,具體工廠,抽象產(chǎn)品,具體產(chǎn)品。

  • 抽象工廠(AbstractCreator):這個角色的是工廠方法模式的核心,它是與應(yīng)用程序無關(guān)的。在此模式中任何創(chuàng)建對象的工廠類必須繼承此類或者實現(xiàn)此接口。
  • 具體工廠(ConcreteCreator):這個角色的是實現(xiàn)了抽象工廠接口的具體Java類。具體工廠角色含有與應(yīng)用密切相關(guān)的邏輯,并且受到應(yīng)用程序的調(diào)用以創(chuàng)建產(chǎn)品對象。
  • 抽象產(chǎn)品(AbstractProduct):工廠方法模式所創(chuàng)建的對象的超類型,也就是產(chǎn)品對象的共同父類或共同擁有的接口。在實際應(yīng)用中這個角色常常由Java的抽象類來實現(xiàn)。
  • 具體產(chǎn)品(ConcreteProduct):這個角色實現(xiàn)了抽象產(chǎn)品角色所聲明的接口,工廠方法所創(chuàng)建的每一個對象都是某個具體產(chǎn)品角色的實例。

工廠方法模式就是對簡單工廠模式的優(yōu)化,增加的只是抽象工廠這個角色,之前工廠類變?yōu)榫唧w工廠類且移除靜態(tài)工廠方法。

工廠方法模式案例解析

情景:增加了晚飯,做飯變成早飯、午飯、晚飯。

抽象工廠(AbstractCreator)用以被具體工廠繼承父類或?qū)崿F(xiàn)共有接口的。如:

/**
 * 抽象工廠-什么飯
 *
 * @author jinzifu
 * @create 2018/2/22 17:54
 */
public interface IFoodFactory {
    /**
     * 獲取餐類
     *
     * @return
     */
    IMakeFood getFood();
}

和簡單工廠模式里一樣,工廠類最終獲取的是具體產(chǎn)品對象實例,且該產(chǎn)品對象實例是統(tǒng)一實現(xiàn)抽象產(chǎn)品接口或繼承抽象產(chǎn)品類的。這里返回的是實現(xiàn)了IMakeFood接口的對象實例。

具體工廠(ConcreteCreator)用于實現(xiàn)需求指定的產(chǎn)品實例,且具體工廠均實現(xiàn)抽象工廠接口或繼承抽象工廠類。如:

/**
 * 具體工廠-晚飯
 *
 * @author jinzifu
 * @create 2018/2/23 22:03
 */
public class DinnerFactory implements IFoodFactory {
    @Override
    public IMakeFood getFood() {
        return new Dinner();
    }
}

新增的晚飯具體產(chǎn)品類Dinner,如:

/**
 * 具體產(chǎn)品-晚飯
 *
 * @author jinzifu
 * @create 2018/2/23 22:04
 */
public class Dinner implements IMakeFood {
    @Override
    public void makeFood() {
        System.out.println("晚飯");
    }
}

外部測試及打印,如:

 DinnerFactory dinnerFactory = new DinnerFactory();
 Dinner dinner = (Dinner) dinnerFactory.getFood();
 dinner.makeFood();

 晚飯

工廠方法模式總結(jié)

  • 在工廠方法模式下,如果要增加產(chǎn)品,只需要擴展對應(yīng)的具體工廠(ConcreteCreator)和具體產(chǎn)品(ConcreteProduct)即可,原有源碼無需改變,遵循了“開閉原則”。
  • 工廠類變?yōu)閷崿F(xiàn)類統(tǒng)一抽象工廠接口或繼承抽象工廠類的具體工廠,具體的產(chǎn)品對象由具體工廠類創(chuàng)建,功能單一,不再臃腫。
  • 具體工廠內(nèi)部不再是靜態(tài)工廠方法,且可繼承抽象工廠類,可形成基于繼承的等級結(jié)構(gòu)。
  • 每次增加具體產(chǎn)品時,具體工廠類和具體產(chǎn)品類都要增加,文件數(shù)成對出現(xiàn)增加了編譯成本。

作為一種創(chuàng)建類模式,在需要生成復(fù)雜對象的地方,都可以考慮使用工廠模式。而工廠方法模式適用最廣。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容