Java設計模式之工廠方法模式
定義一個用於建立物件的介面,讓子類決定例項化哪個類。工廠方法使一個類的例項化延遲到其子類。
工廠方法與簡單工廠
對於簡單工廠模式,我們知道其在工廠類中包含了必要的邏輯判斷,根據不同的條件來動態例項化相關類。對於客戶端來說,這去除了與具體產品的依賴;但於此同時也帶來了一個問題:如果我們要增加產品,比如我們要生產蘋果計算機,就需要在工廠類中新增一個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(); } } 複製程式碼