在上篇文章工廠模式——工廠方法模式中,我們根據(jù)案例學(xué)習(xí)了工廠方法模式知識(shí)點(diǎn)。此篇我們引入新的需求場(chǎng)景下,在對(duì)比工廠方法模式下學(xué)習(xí)抽象工廠模式的運(yùn)用。
產(chǎn)品族和等級(jí)結(jié)構(gòu)
為了更清晰地理解抽象工廠模式,需要先引入兩個(gè)概念:
- 產(chǎn)品族:在抽象工廠模式中,產(chǎn)品族是指由同一個(gè)工廠生產(chǎn)的,位于不同產(chǎn)品等級(jí)結(jié)構(gòu)中的一組產(chǎn)品,如海爾電器工廠生產(chǎn)的海爾電視、海爾洗衣機(jī)。
- 等級(jí)結(jié)構(gòu):產(chǎn)品等級(jí)結(jié)構(gòu)即產(chǎn)品的繼承結(jié)構(gòu),如抽象電視機(jī)與具體品牌的電視機(jī)之間構(gòu)成了一個(gè)產(chǎn)品等級(jí)結(jié)構(gòu)。
由此可見(jiàn),工廠方法模式就是一個(gè)產(chǎn)品族下的等級(jí)結(jié)構(gòu)體系,是抽象工廠模式的特殊情況。
抽象工廠模式組成角色
- AbstractFactory(抽象工廠):它聲明了一組用于創(chuàng)建一族產(chǎn)品的方法,每一個(gè)方法對(duì)應(yīng)一種產(chǎn)品。
- ConcreteFactory(具體工廠):它實(shí)現(xiàn)了在抽象工廠中聲明的創(chuàng)建產(chǎn)品的方法,生成一組具體產(chǎn)品,這些產(chǎn)品構(gòu)成了一個(gè)產(chǎn)品族,每一個(gè)產(chǎn)品都位于某個(gè)產(chǎn)品等級(jí)結(jié)構(gòu)中。
- AbstractProduct(抽象產(chǎn)品):它為每種產(chǎn)品聲明接口或抽象父類。
- ConcreteProduct(具體產(chǎn)品):它定義具體工廠生產(chǎn)的具體產(chǎn)品對(duì)象,實(shí)現(xiàn)抽象產(chǎn)品接口中聲明的業(yè)務(wù)方法。
此模式下的抽象工廠創(chuàng)建的是一族產(chǎn)品中的所有子產(chǎn)品,而工廠方法模式下的抽象工廠對(duì)應(yīng)的是子產(chǎn)品的聲明。即工廠方法模式下的抽象工廠角色定位被抽象工廠模式下的抽象工廠角色的方法代替。
抽象工廠模式案例解析
案例情景:王師傅和李師傅各輪值一天,但想吃王師傅做的早飯、午飯、晚飯。
若要今天吃到王師傅做的早飯,就不能在今天吃李師傅做的午飯或晚飯,因?yàn)楫?dāng)天只會(huì)有一個(gè)師傅值班。
王師傅和李師傅做的飯就是兩個(gè)產(chǎn)品族。做飯和做早飯遵循等級(jí)結(jié)構(gòu)中的繼承結(jié)構(gòu)。
以往的工廠方法模式卻無(wú)法區(qū)分早飯、午飯、晚飯分屬的產(chǎn)品族,這就需抽象工廠模式的由來(lái)。
抽象工廠接口,如下:
/**
* 抽象工廠- 李師傅做飯
*
* @author jinzifu
* @create 2018/2/23 22:04
*/
public interface ILiFoodFactory {
/**
* 早飯
*
* @return
*/
IMakeFood getBreakfest();
/**
* 午飯
*
* @return
*/
IMakeFood getLunch();
/**
* 晚飯
*
* @return
*/
IMakeFood getDinner();
}
該接口內(nèi)的方法聲明了一個(gè)產(chǎn)品族內(nèi)的所有子產(chǎn)品,如李師傅做的早飯、午飯、晚飯。早飯、午飯、晚飯是兩個(gè)產(chǎn)品族(王師傅和李師傅)共有的等級(jí)結(jié)構(gòu)。
具體工廠類,如下:
/**
* 具體工廠-李師傅做飯
*
* @author jinzifu
* @create 2018/2/24 11:11
*/
public class LiFoodFactory implements ILiFoodFactory {
public LiFoodFactory() {
System.out.println("李師傅值班中...");
}
@Override
public IMakeFood getBreakfest() {
return new Breakfest();
}
@Override
public IMakeFood getLunch() {
return new Lunch();
}
@Override
public IMakeFood getDinner() {
return new Dinner();
}
}
具體工廠實(shí)現(xiàn)抽象工廠接口中的所有具體產(chǎn)品,如早飯、午飯、晚飯。
此模式下的抽象產(chǎn)品和具體產(chǎn)品與工廠方法模式下承擔(dān)的角色和分工一樣,不做贅述。
外部測(cè)試及打印如下:
LiFoodFactory liFoodFactory = new LiFoodFactory();
liFoodFactory.getBreakfest().makeFood();
liFoodFactory.getLunch().makeFood();
liFoodFactory.getDinner().makeFood();
李師傅值班中...
早飯
午飯
晚飯
抽象工廠模式下,產(chǎn)品的擴(kuò)展需更改抽象工廠的接口方法,違背了“開(kāi)閉原則”。
工廠模式的使用場(chǎng)景
- 產(chǎn)品的創(chuàng)建過(guò)程較為復(fù)雜,且創(chuàng)建和使用分離開(kāi)進(jìn)行更好時(shí)宜采用工廠模式。
- 系統(tǒng)產(chǎn)品分屬多個(gè)產(chǎn)品族,產(chǎn)品族之間有相似的產(chǎn)品等級(jí)結(jié)構(gòu),且同一時(shí)刻系統(tǒng)只消費(fèi)其中某一族的產(chǎn)品時(shí),宜采用抽象工廠模式。
- 單一產(chǎn)品族時(shí),多采用工廠方法模式。只需增加工廠類和具體產(chǎn)品類,符合“開(kāi)閉原則”。