定義
定義一個用於建立物件的介面,讓子類決定例項化哪個類。工廠方法使一個類的例項化延遲到其子類。
工廠方法與簡單工廠
對於簡單工廠模式,我們知道其在工廠類中包含了必要的邏輯判斷,根據不同的條件來動態例項化相關類。對於客戶端來說,這去除了與具體產品的依賴;但於此同時也帶來了一個問題:如果我們要增加產品,比如我們要生產蘋果計算機,就需要在工廠類中新增一個
Case
分支條件,這違背了開放封閉原則,對修改也開放了。而工廠方法模式就沒有違背這個開放封閉原則。如果我們需要生產蘋果電腦,則無需修改工廠類,直接建立產品即可。
角色
- Product:抽象產品類。
- ConcreteProduct:具體產品類,實現
Product
介面。 - Factory:抽象工廠類,該方法返回一個
Product
型別的物件。 - ConcreteFactory:具體工廠類,返回
ConcreteProduct
例項。
工廠方法模式的簡單實現
- 首先建立一個計算機的抽象產品類,其中有一個抽象方法使用者啟動計算機生產:
public abstract class Computer {
/**
* 產品的抽象方法,由具體的產品類實現
*/
public abstract void start();
}
複製程式碼
- 接著我們建立各個品牌的計算機,其都繼承了自己的父類
Computer
,並實現了父類的start
方法。
public class LenovoComputer extends Computer {
@Override
public void start() {
System.out.println("聯想計算機啟動");
}
}
public class HpComputer extends Computer {
@Override
public void start() {
System.out.println("惠普計算機啟動");
}
}
public class AsusComputer extends Computer {
@Override
public void start() {
System.out.println("華碩計算機啟動");
}
}
複製程式碼
- 建立抽象工廠類,裡面有一個
createComputer
方法,用於生產各種品牌的計算機。
public abstract class ComputerFactory {
public abstract <T extends Computer> T createComputer(Class<T> clz);
}
複製程式碼
- 建立具體工廠,廣大代工廠是一個具體的工廠,其繼承抽象工廠,通過反射來生產不同廠家的計算機。
public class GDComputerFactory extends ComputerFactory {
@Override
public <T extends Computer> T createComputer(Class<T> clz) {
Computer computer = null;
String className = clz.getName();
try {
//通過反射來生產不同廠家的計算機
computer = (Computer)Class.forName(className).newInstance();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return (T) computer;
}
}
複製程式碼
- 客戶端呼叫,客戶端建立
GDComputerFactory
生產各種計算機。
public class Client {
public static void main(String[] args) {
ComputerFactory computerFactory = new GDComputerFactory();
LenovoComputer mLenovoComputer = computerFactory.createComputer(LenovoComputer.class);
mLenovoComputer.start();
HpComputer mHpComputer = computerFactory.createComputer(HpComputer.class);
mHpComputer.start();
AsusComputer mAsusComputer = computerFactory.createComputer(AsusComputer.class);
mAsusComputer.start();
}
}
複製程式碼