參考文章:
漫畫:設(shè)計(jì)模式之 “工廠模式”
漫畫:什么是 “抽象工廠模式” 裤园?
自己簡單總結(jié)一下撤师,加強(qiáng)下記憶。
簡單工廠模式
就一個(gè)工廠類拧揽,里面通過if-else判斷邏輯來決定生產(chǎn)哪個(gè)產(chǎn)品剃盾。比如:
class SimpleFactory {
public Product createdProduct(String type){
if("1".equels(type)){
//創(chuàng)建產(chǎn)品A
} else if("2".equels(type)){
//創(chuàng)建產(chǎn)品B
}
}
}
簡單工廠可以滿足簡單業(yè)務(wù)場景下的需求,但是如果type類型很多淤袜,這里的if-else豈不是要一大堆痒谴。并且隨著業(yè)務(wù)的發(fā)展,type可以繼續(xù)增加铡羡,每次增加都需要修改工廠的判斷邏輯积蔚,不滿足開閉原則。
工廠方法模式
上面簡單工廠的缺點(diǎn):不能適應(yīng)type的拓展烦周,不滿足開閉原則尽爆。
為了消除if-else,我們需要調(diào)用者自己決定生產(chǎn)哪些產(chǎn)品读慎。問題來了漱贱,如果讓調(diào)用方直接new 不同的產(chǎn)品,那還需要設(shè)計(jì)模式干嘛夭委。所以饱亿,這里我們讓調(diào)用者決定生產(chǎn)產(chǎn)品,不是直接new產(chǎn)品闰靴,而是直接調(diào)用產(chǎn)品工廠彪笼。
所以,我們可知工廠方法模式需要?jiǎng)?chuàng)建多個(gè)工廠類蚂且,來給調(diào)用方使用配猫。每個(gè)工廠類,只負(fù)責(zé)自己的產(chǎn)品生產(chǎn)杏死。這樣的話泵肄,調(diào)用方只需要new產(chǎn)品工廠即可。
服務(wù)端代碼如下:
public interface IMaskFactory {
IMask createMask();
}
public class HighEndFactory implements IMaskFactory{
@Override
public IMask createMask() {
IMask mask = new HighEndMask();
// .....
// HighEndMask的100行初始化代碼
return mask;
}
}
public class LowEndFactory implements IMaskFactory{
@Override
public IMask createMask() {
IMask mask = new LowEndMask();
// .....
// LowEndMask的100行初始化代碼
return mask;
}
}
客戶端代碼如下:
public class Test {
public static void main(String[] args) {
IMaskFactory factoryA = new LowEndFactory();
IMaskFactory factoryB = new HighEndFactory();
IMask maskA = factoryA.createMask();
IMask maskB = factoryB.createMask();
maskA.show();
maskB.show();
}
}
你可能會(huì)覺得new工廠類淑翼,和new 產(chǎn)品類腐巢,有啥不一樣⌒ǎ客戶端代碼冯丙,一行也沒少寫,想要修改客戶端需求遭京,還是得改客戶端代碼胃惜。
我們可以從另外一個(gè)角度看:new工廠類泞莉,不new 產(chǎn)品類,相當(dāng)于把產(chǎn)品和客戶端解耦了船殉,用工廠類這個(gè)中間人來黏和鲫趁。這樣的話,我們想改產(chǎn)品類利虫,只要改對應(yīng)的工廠類即可挨厚。達(dá)到解耦的效果,是不是有點(diǎn)spring ioc的味道了糠惫。
這種模式也有缺點(diǎn):每個(gè)產(chǎn)品都需要對應(yīng)一個(gè)工廠類疫剃,每增加一個(gè)產(chǎn)品,都必須相應(yīng)增加工廠類寞钥,導(dǎo)致類數(shù)量爆炸式增長慌申。
克服這種缺點(diǎn),我們就必須再抽象一個(gè)層次理郑。比如:提取各個(gè)產(chǎn)品的共性蹄溉,根據(jù)共性創(chuàng)建抽象工廠。
舉個(gè)例子:口罩和防護(hù)服兩個(gè)產(chǎn)品您炉,我們現(xiàn)在要添加一個(gè)高端和低端兩個(gè)質(zhì)量柒爵,用工廠方法的話,就需要 2 * 2 = 4個(gè)工廠類(高端口罩赚爵、低端口罩棉胀、高端防護(hù)服和低端防護(hù)服)。如果產(chǎn)品不止兩個(gè)呢冀膝,比如20個(gè)產(chǎn)品都需要高端和低端唁奢,那么工廠方法模板就需要40個(gè)工廠類。這種增加速度太快了窝剖,無法接受麻掸。
所以抽象工廠模式應(yīng)運(yùn)而生,對產(chǎn)品提取共性:高端和低端赐纱。那么就創(chuàng)建兩個(gè)抽象工廠類:高端工廠類和低端工廠類脊奋。這兩個(gè)抽象類,其實(shí)并不能生產(chǎn)具體產(chǎn)品疙描。只能知道诚隙,高端工廠類能生成高端的產(chǎn)品,至于產(chǎn)品是誰并不知道起胰。所以久又,這種方法簡單的解決方法就是通過抽象工廠類的方法來解決。
每個(gè)抽象類里面,有不同產(chǎn)品的創(chuàng)建方法籽孙。這些方法都只會(huì)創(chuàng)建高端產(chǎn)品或低端產(chǎn)品烈评。
如下:
public interface IFactory {
//創(chuàng)建口罩
IMask createMask();
//創(chuàng)建防護(hù)服
IProtectiveSuit createSuit();
}
public class LowEndFactory implements IFactory {
@Override
public IMask createMask() {
IMask mask = new LowEndMask();
// .....
// LowEndMask的100行初始化代碼
return mask;
}
@Override
public IProtectiveSuit createSuit() {
IProtectiveSuit suit = new LowEndProtectiveSuit();
// .....
// LowEndProtectiveSuit的100行初始化代碼
return suit;
}
}
public class HighEndFactory implements IFactory {
@Override
public IMask createMask() {
IMask mask = new HighEndMask();
// .....
// HighEndMask的100行初始化代碼
return mask;
}
@Override
public IProtectiveSuit createSuit() {
IProtectiveSuit suit = new HighEndProtectiveSuit();
// .....
// HighEndProtectiveSuit的100行初始化代碼
return suit;
}
}
createMask和createSuit是創(chuàng)建產(chǎn)品的接口方法火俄,每個(gè)具體工廠類只會(huì)生產(chǎn)高端或低端產(chǎn)品犯建。
這樣的話,就只需要兩個(gè)工廠類瓜客,而非40個(gè)工廠類适瓦。
但是接口方法會(huì)有40個(gè)產(chǎn)品方法,這個(gè)是沒法省的谱仪。
但是它也有缺點(diǎn):
客戶端再使用的時(shí)候玻熙,只需要高端口罩。但是拿到的是高端工廠疯攒,可以生產(chǎn)所有高端產(chǎn)品包括:高端口罩嗦随,高端防護(hù)服和高端其他產(chǎn)品。這樣也很危險(xiǎn)敬尺,看到了不需要的功能枚尼,違背了最小原則。