工廠方法模式
工廠方法模式是類的創建模式。工廠方法模式的用意是定義一個創建產品對象的工廠接口,將實際創建工廠推遲到子類中。
工廠方法模式
工廠方法模式是對簡單工廠模式進一步抽象的結果。
假如是不使用反射的工廠方法模式,那么所有的if...
else if...else都放在工廠類中,勢必造成工廠類的無限臃腫
這時候就需要工廠方法模式來處理這個問題了。工廠方法模式中,核心的工廠類不再負責所有對象的創建,而是將具體的創建工作交給子類去做。這個類則搖身一變變成了一個抽象工廠角色,僅僅負責給出具體工廠子類必須實現的接口。
這一步的改進,使得系統可以在不修改具體工廠角色的情況下引入新的產品。
工廠方法模式結構
使用工廠方法模式的系統涉及到以下角色:
1、抽象工廠角色
擔任這個角色的是工廠方法模式的核心,任何在模式中創建對象的工廠類必須實現這個接口
2、具體工廠角色
擔任這個角色的是實現了工廠接口的具體Java類,具體工廠角色與業務密切相關,並且隨着使用者的調用以創建導出類
3、抽象導出角色
工廠方法模式所創建的對象的超類
4、具體導出角色
這個角色實現了抽象導出角色所聲明的接口,工廠方法模式所創建的每一個對象都是某個具體角色導出角色的實例
工廠方法模式的示例
有一個抽象工廠,導出文件的工廠:
public interface ExportFactory { public ExportFile factory(String type); }
它有兩個實現類,分別是導出HTML文件的工廠和導出PDF文件的工廠:
public class ExportHtmlFactory implements ExportFactory { public ExportFile factory(String type) { if ("standard".equals(type)) { return new ExportStandardHtmlFile(); } else if ("financial".equals(type)) { return new ExportFinancialHtmlFile(); } return null; } }
public class ExportPdfFactory implements ExportFactory { public ExportFile factory(String type) { if ("standard".equals(type)) { return new ExportStandardPdfFile(); } else if ("financial".equals(type)) { return new ExportFinancialPdfFile(); } return null; } }
抽象產品角色,一個導出文件:
public interface ExportFile { public boolean export(String data); }
具體產品角色:
public class ExportFinancialHtmlFile implements ExportFile { public boolean export(String data) { System.out.println("導出財務版HTML文件"); return false; } }
public class ExportFinancialPdfFile implements ExportFile { public boolean export(String data) { System.out.println("導出財務版PDF文件"); return true; } }
public class ExportStandardHtmlFile implements ExportFile { public boolean export(String data) { System.out.println("導出標准HTML文件"); return true; } }
public class ExportStandardPdfFile implements ExportFile { public boolean export(String data) { System.out.println("導出標准PDF文件"); return true; } }
模擬客戶端調用,實例化出一個具體的工廠角色,根據傳入的參數返回不同的產品角色:
public static void main(String[] args) { String data = ""; ExportFactory exportFactory = new ExportHtmlFactory(); ExportFile ef = exportFactory.factory("financial"); ef.export(data); }
返回結果為:
導出財務版HTML文件
當然,也可以修改代碼,看自己喜好,實例化出不同的子類並且調用export方法打印。
工廠方法模式在Java中的應用及解讀
拿ThreadFactory舉個例子,顧名思義,這是一個生產線程的接口:
public interface ThreadFactory { /** * Constructs a new {@code Thread}. Implementations may also initialize * priority, name, daemon status, {@code ThreadGroup}, etc. * * @param r a runnable to be executed by new thread instance * @return constructed thread, or {@code null} if the request to * create a thread is rejected */ Thread newThread(Runnable r); }
具體的線程工廠可以implements這個接口並實現newThread(Runnable r)方法,來生產具體線程工廠想要生產的線程。JDK在Executors給開發者提供了一個靜態內部類DefaultThreadFactory,當然開發者也可以自行實現這個接口,寫自定義的線程工廠。
總結
對於系統的設計應該足夠靈活並盡可能降低代碼之間的耦合度,當修改或增加一個新的功能時,使得使用者盡可能修改少的地方即可。假如設計不夠靈活,將無法面對多變的需求,可能一個極小的需求變更,都會使代碼結構發生改變,並導致其他使用的人都要修改他們的代碼。牽一發而動全身,系統日后的維護將變得艱難。
