一、工廠方法模式的本質(zhì)
工廠方法模式的本質(zhì)是在簡(jiǎn)單工廠的基礎(chǔ)上,分離簡(jiǎn)單工廠的職責(zé),實(shí)現(xiàn)不同具體產(chǎn)品類實(shí)例創(chuàng)建職責(zé)分離的。(在簡(jiǎn)單工廠中,所有的產(chǎn)品類實(shí)例對(duì)象的創(chuàng)建都有同一個(gè)工廠實(shí)現(xiàn),導(dǎo)致了工廠類的職責(zé)過多,影響了開閉原則)
工廠方法模式的核心就是為每一個(gè)具體產(chǎn)品類提供各自的工廠,有對(duì)應(yīng)的工廠創(chuàng)建對(duì)應(yīng)的產(chǎn)品類實(shí)例對(duì)象,體現(xiàn)了單依職責(zé)的設(shè)計(jì)理念,保證了開閉原則的遵循。
二、工廠方法模式目的
與簡(jiǎn)單工廠模式類似,工廠方法模式的核心目標(biāo)也是將“類實(shí)例化的操作”與“使用對(duì)象的操作”分開,相對(duì)于簡(jiǎn)單工廠模式。
三、示例場(chǎng)景
同簡(jiǎn)單工廠。
某個(gè)電腦公司的在線購(gòu)物網(wǎng)站可售賣不同型號(hào)的筆記本電腦,網(wǎng)站需要為客戶提供電腦的配置信息查看功能,每當(dāng)用戶想查看某個(gè)型號(hào)的電腦配置時(shí),需要給出該型號(hào)電腦的CPU、內(nèi)存大小、硬盤類型和大小、生產(chǎn)日期以及價(jià)格等信息。
注意事項(xiàng):該公司可能每季度都有新型號(hào)的電腦上架。
四、代碼實(shí)現(xiàn)及對(duì)比
抽象產(chǎn)品類定義
public interface IThinkpad {
String getConfigInfo();
}
Thinkpad X1產(chǎn)品類定義
public class X1 implements IThinkpad{
String cpu;
int memory;
int hardDriveCapacity;
String hardDriveType;
/*屬性的getter、setter以及toString方法省略*/
public IThinkpad createThinkPad(){
this.cpu = "英特爾 i7 10570U ";
this.memory = 32;
this.hardDriveType = "Seagate HDD";
this.hardDriveCapacity = 512;
return this;
}
public String getConfigInfo() {
return "Thinkpad X1 配置信息如下:\n--"+cpu + "\n--" + memory + "\n--" + hardDriveCapacity + "\n--" + hardDriveType;
}
}
Thinkpad X1Pro產(chǎn)品類定義
public class X1Pro implements IThinkpad{
String cpu;
int memory;
int hardDriveCapacity;
String hardDriveType;
/*屬性的getter、setter以及toString方法省略*/
public String getConfigInfo() {
return "Thinkpad X1 Pro 配置信息如下:\n--"+cpu + "\n--" + memory + "\n--" + hardDriveCapacity + "\n--" + hardDriveType;
}
}
抽象產(chǎn)品工廠接口定義
public interface IThinkpadFactory {
IThinkpad createThinkpad();
}
具體產(chǎn)品類定義-X1具體工廠類
public class X1FactoryImpl implements IThinkpadFactory {
@Override
public IThinkpad createThinkpad() {
X1 x1 = new X1();
x1.createThinkPad();
return x1;
}
}
具體產(chǎn)品類定義-X1Pro具體工廠類
public class X1ProFactoryImpl implements IThinkpadFactory {
@Override
public IThinkpad createThinkpad() {
X1Pro x1Pro = new X1Pro();
x1Pro.setCpu("英特爾 i9 13770H ");
x1Pro.setMemory(64);
x1Pro.setHardDriveType("Seagate SSD");
x1Pro.setHardDriveCapacity(2048);
return x1Pro;
}
}
客戶端類定義
public class com.financial.builderpattern.complex.Main {
public static void main(String[] args) {
IThinkpad x1 = new X1FactoryImpl().createThinkpad();
System.out.println(x1.getConfigInfo());
IThinkpad x1pro = new X1ProFactoryImpl().createThinkpad();
System.out.println(x1pro.getConfigInfo());
}
}
工廠方法模式中相關(guān)關(guān)系圖

簡(jiǎn)單工廠模式中相關(guān)關(guān)系圖

從上面兩張類圖可以看出,工廠方法模式就是將簡(jiǎn)單工廠模式中的工廠類進(jìn)行了抽象,并針對(duì)不同的產(chǎn)品進(jìn)行了分別實(shí)現(xiàn)。
現(xiàn)在再看看黨需要增加一個(gè)產(chǎn)品X1ProMax類的時(shí)候,兩者的不同點(diǎn)。


可以看出,黨需要新增產(chǎn)品類的時(shí)候,簡(jiǎn)單工廠需要只能加一個(gè)響應(yīng)的具體產(chǎn)品類并在工廠類中增加響應(yīng)新產(chǎn)品類實(shí)例對(duì)象創(chuàng)建的邏輯。而在工廠方法模式中,僅需要增加新的具體產(chǎn)品類和具體產(chǎn)品工廠類就行??梢钥闯觯谶@樣的需求場(chǎng)景下,簡(jiǎn)單工廠破壞了開閉原則,而工廠方法則可保證開閉原則。
五、工廠方法的UML類圖

工廠方法模式中的角色:
(1)抽象產(chǎn)品:抽象定義產(chǎn)品的通用屬性和方法,可以用Java中的interface或者abstract class來(lái)實(shí)現(xiàn),如IThinkpad;
(2)具體產(chǎn)品:不同產(chǎn)品具有不同的屬性值和方法實(shí)現(xiàn),如X1、X1Pro;
(3)抽象工廠:抽象不同產(chǎn)品的創(chuàng)建方法,如IThinkpadFactory;
(4)具體工廠類:負(fù)責(zé)按照客戶端的“要求”(如參數(shù)、類的類型等),提供創(chuàng)建具體產(chǎn)品類的方法,產(chǎn)品類的創(chuàng)建(即new)在此類中實(shí)現(xiàn)并返回抽象產(chǎn)品類型的具體產(chǎn)品實(shí)例,如X1FactoryImpl、X1ProFactoryImpl;
(5)客戶端類:創(chuàng)建簡(jiǎn)單工廠類并向其傳入相應(yīng)產(chǎn)品的參數(shù),接受產(chǎn)品工廠返回的產(chǎn)品類實(shí)例對(duì)象。
六、工廠方法的優(yōu)缺點(diǎn)
(1)優(yōu)點(diǎn)
除了具備簡(jiǎn)單工廠的優(yōu)點(diǎn)外,相對(duì)于簡(jiǎn)單工廠,工廠方法更加符合開閉原則;
(2)缺點(diǎn)
增加了累的數(shù)量,相對(duì)于簡(jiǎn)單工廠,工廠方法由于針對(duì)每個(gè)產(chǎn)品都會(huì)有一個(gè)產(chǎn)品工廠類與之對(duì)應(yīng),所以其類的數(shù)量相對(duì)會(huì)增多;
與簡(jiǎn)單工廠類似,工廠方法適用于擴(kuò)展多、修改少的產(chǎn)品類場(chǎng)景,如果修改原有的產(chǎn)品類,則相應(yīng)的工廠類也可能需要修改;