解決問題
主要解決創(chuàng)建復(fù)雜對象的問題。
應(yīng)用場景
當(dāng)某一系列對象需要復(fù)雜的邏輯控制創(chuàng)建過程,過程創(chuàng)建過程比較復(fù)雜時,可以采用工廠模式。
工廠模式常見的有三種:
簡單工廠模式: 又稱之為靜態(tài)工廠模式
工廠模式:最常見的一種工廠模式具壮,用于生產(chǎn)一系列相似的對象
抽象工廠模式:可用于生產(chǎn)各種各樣的對象(用于較復(fù)雜的場景)
下面我們來一一介紹
原理與示例
以我們?nèi)ワ埖瓿燥垶槔?/p>
簡單工廠模式(simple factory ,static factory)
類似于其名稱,它適合于比較簡單的場景哈蝇,通過提供一個靜態(tài)方法來創(chuàng)建對象棺妓。
這次我們?nèi)サ氖且粋€小飯店,就一個廚師炮赦,只會做西紅柿炒雞蛋和下面條怜跑。。吠勘。性芬。。原理圖如下所示
public abstract class Food {
}
public class Noodle extends Food {
}
public class TomatoOmelette extends Food {
}
public class Factory {
public static Food createFood(@Nonnull String food) {
if (food.equals("noodle")) {
return new Noodle();
}
if (food.equals("TomatoOmelette")) {
return new TomatoOmelette();
}
return null;
}
}
public class Client {
public static void main(String[] args) {
// 想吃面條
Food food = Factory.createFood("noodle");
//.....
}
}
這種工廠模式的好處在于剧防,屏蔽了客戶端與對象的直接交互(就是我作為客戶去吃飯植锉,沒有讓我自己做飯的道理),只需要告訴飯店需要吃什么菜就可以了峭拘。
但它的壞處也是明顯的俊庇,它并沒有降低創(chuàng)造對象的復(fù)雜度狮暑,仍然需要許多if 業(yè)創(chuàng)建對象,對于多種類對象并不合適辉饱。所以也能適合簡單場景
工廠方法模式
后來這個小餐館竟然賺錢了搬男,客人越來越多,廚師抱怨了鞋囊,做兩種食物忙不過來止后,老板就又招了一個廚師,讓每一人負(fù)責(zé)一道菜溜腐。
public abstract class Food {
}
public class Noodle extends Food {
}
public class TomatoOmelette extends Food {
}
public interface Factory {
public Food create();
}
public class NoodleFactory implements Factory {
@Override
public Food create() {
return new Noodle();
}
}
public class TomatoOmeletteFactory implements Factory {
@Override
public Food create() {
return new TomatoOmelette();
}
}
public class Client {
public static void main(String[] args) {
// 想吃面條
Food food = new NoodleFactory().create();
//.....
}
}
因為我們是老顧客了,所以到了餐館之后瓜喇,只需要告訴對應(yīng)的廚師你想吃飯就行了挺益,到于你想吃什么飯,由你告訴的廚師來決定乘寒。
該模式相當(dāng)于將創(chuàng)建不同種類的對象的邏輯給隔離開了望众,特別對于創(chuàng)建邏輯差異化較大的對象,此時就對應(yīng)的工廠各司其職伞辛。就像生產(chǎn)自行車的一定不可能與生產(chǎn)汽車的在一條生產(chǎn)線上一樣烂翰。
該模式雖然做了復(fù)雜性分離,但其惡心之處在于蚤氏,你竟然得先創(chuàng)建一個工廠甘耿。就比如你想吃面條,你得創(chuàng)建一個工廠竿滨,這個成本是不可接受的佳恬。所以后來又有了抽象工廠模式。
抽象工廠模式
老板的這一招改進(jìn)于游,讓自己的生意更加火爆毁葱。他決定擴(kuò)展自己的業(yè)務(wù),將自己的業(yè)務(wù)擴(kuò)展成兩個系列:面條系列(炸醬面贰剥、雞蛋面倾剿、拉面、扯面蚌成。前痘。。)笑陈,炒菜(西紅柿雞蛋际度、青椒土豆絲、酸辣大白菜等)涵妥。當(dāng)我再次來到飯店時乖菱,廚師已經(jīng)都不認(rèn)識了坡锡,咋點菜呢?“服務(wù)員窒所,來一碗面雞蛋面鹉勒!”。這種方式由就需要抽象工廠來實現(xiàn)了吵取。工廠方法模式雖然能夠?qū)崿F(xiàn)禽额,但已經(jīng)過于復(fù)雜了,需要定義太多的factory皮官。
炒菜系就不再畫了脯倒,多個Factory之間仍然可以選擇三種工廠模式來解決創(chuàng)建工廠的問題。
來看一下示例吧
public abstract class Food {
}
public class EggNoodle extends Food {
}
public class LaNoodle extends Food {
}
public interface AbstractNoodleFactory {
public Food createLaNoodle();
public Food createEggNoodle();
}
public class NoodleFactory implements AbstractNoodleFactory {
public Food createLaNoodle() {
return new LaNoodle();
}
public Food createEggNoodle() {
return new EggNoodle();
}
}
public class Client {
public static void main(String[] args) {
// 想吃拉面
Food food = new NoodleFactory().createLaNoodle();
//.....
}
}
抽象工廠模式捺氢,解決了更加復(fù)雜一些的問題藻丢,它更像一個具有多條生產(chǎn)線工廠,可以生產(chǎn)各種產(chǎn)品摄乒。
但還是強(qiáng)調(diào)一下悠反,任何一種設(shè)計模式在實際應(yīng)用時,往往都不是單獨使用的馍佑;因為現(xiàn)實問題更加復(fù)雜斋否,需要你結(jié)合其它生產(chǎn)模式一起使用。三種工廠模式各有用途拭荤,在實際使用時茵臭,可以簡單選擇,也可以相互組合穷劈,以解決你的實際問題笼恰。