工廠方法模式

《研磨設計模式》之工廠方法模式

一、應用場景

實現一個能導出數據到各種文件格式(txt,DBFile,Excel,Xml)的應用框架.

1.不管用戶導出神馬樣的文件格式,都要進行一個導出的操作.

2.系統不知道用戶會導出哪種格式的文件

書中描述,框架是一個半成品,開發者可以在此基礎上完成軟件功能。因此具體是導出神馬樣的格式,是由具體的開發者(本例是Client類)決定的.

根據1.都要進行一個導出操作,因此要定義具有導出功能的接口

   1: /**
   2:  * 定義數據導出的功能的接口
   3:  * @author YoungCold
   4:  *
   5:  */
   6: public interface ExportFileApi {
   7:     /**
   8:      * 將數據導出成文件(具體文件格式有實現類決定)
   9:      * @param data
  10:      * @return
  11:      */
  12:     public boolean export(String data);
  13: }
對於導出數據的業務功能對象,也就是用ExportFileApi定義的導出數據的方法export()完成導出數據這一功能的類的實例.它需要根據用戶的需要(比如,用戶選擇導出數據到Excel文件)創建相應的ExportFileApi對象(實現ExportFileApi定義的export():將數據導出到Excel),也就是說特定的ExportFileApi實現由實際情況決定。
問題是,業務功能對象不知道如何創建ExportFileApi的對象(實際上,也不需要知道)
二、工廠模式
工廠方法的定義:定義一個用於創建對象的接口,讓子類決定實例化哪一個類①,Factory Method使一個類②的實例化延遲到子類。
補充:就對應用場景而言,個人感覺,①和②指的是同一個類——實現ExportFileApi的類。
 
前面提過,實現導出功能的業務類跟本不知道實際會選擇哪種導出數據的格式,因此該對象就不應該和具體的導出文件對象(實現ExportFileApi的類)耦合在一起,只需要知道ExportFileApi接口即可。
 
這樣一來,業務類要求不能和ExportFileApi具體實現類耦合,但業務類同時要實現導出數據的功能,這就必然要用到ExportFileApi具體實現類的功能。
解決方法:既然需要接口對象,那就定義一個方法創建接口對象。但事實上,業務類並不知道要創建哪種接口對象,因此創建接口對象的任務就由業務類的子類完成,比方說是導出txt文件的業務類(業務類的子類)完成,這樣導出txt文件的業務類負責創建出接口對象,該接口對象完成數據導出到txt的功能。
所以,業務類的創建接口對象的方法就定義成抽象方法。
1.實現導出功能的業務類是個抽象類
2.具體的導出操作有業務類的子類完成
 
數據導出功能業務類
   1: /**
   2:  * 實現導出數據的業務功能對象
   3:  * 即使用數據導出的工具類,實現實際的數據導出
   4:  * @author YoungCold
   5:  *
   6:  */
   7: public abstract class ExportOperate {
   8:     public boolean export(String data){
   9:         ExportFileApi exporter = createExportFileApi();
  10:         return exporter.export(data);
  11:     }
  12:     
  13:     public abstract ExportFileApi createExportFileApi();
  14: }
數據導出功能業務類的子類,實現具體的導出功能(創建何種接口對象)
 
接口對象(實現數據導出到txt文件)
   1: /**
   2:  * 導出數據的工具類,實現數據導出到文本文件
   3:  * @author YoungCold
   4:  *
   5:  */
   6: public class ExportTxtFile implements ExportFileApi {
   7:  
   8:     @Override
   9:     public boolean export(String data) {
  10:         System.out.println("導出數據"+data+"到文本文件");
  11:         return true;
  12:     }
  13:  
  14: }
 
接口對象(實現數據導出到數據庫文件)
   1: /**
   2:  * 導出數據的工具類,實現數據導出到數據庫文件
   3:  * @author YoungCold
   4:  *
   5:  */
   6: public class ExportDBFile implements ExportFileApi {
   7:  
   8:     @Override
   9:     public boolean export(String data) {
  10:         System.out.println("導出數據"+data+"到數據庫文件");
  11:         return true;
  12:     }
  13:  
  14: }
 
數據導出業務類(負責創建 數據導出到txt文件的接口對象)
   1: public class ExportTxtFileOperate extends ExportOperate {
   2:  
   3:     @Override
   4:     public ExportFileApi createExportFileApi() {
   5:         // 創建數據導出到txt文件的接口對象
   6:         return new ExportTxtFile();
   7:     }
   8:  
   9: }
 
數據導出業務類(負責創建 數據導出到數據庫文件的接口對象)
   1: public class ExportDBFileOperate extends ExportOperate {
   2:  
   3:     @Override
   4:     public ExportFileApi createExportFileApi() {
   5:         //  創建數據導出到數據庫文件的接口對象
   6:         return new ExportDBFile();
   7:     }
   8:  
   9: }

 

這樣,當用戶選擇數據導出到具體格式的文件時,我們只需要創建這種文件格式的業務類的對象即可。

比如,用戶選擇數據導出到數據庫文件

   1: String data = "2013-1-13";//要導出的數據
   2: ExportOperate exporter1 = new ExportDBFileOperate();//要導出到數據庫文件,就創建導出到數據庫的業務類對象
   3: exporter1.export(data);//執行導出操作

用戶選擇數據導出到txt文件

   1: String data = "2013-1-13";
   2: ExportOperate exporter2 = new ExportTxtFileOperate();//要導出到txt文件,就創建導出到txt的業務類對象
   3: exporter2.export(data);
再來看數據導出業務抽象類,所實現的數據導出方法
   1: public boolean export(String data){
   2:     ExportFileApi exporter = createExportFileApi();
   3:     return exporter.export(data);
   4: }
ExportFileApi exporter = createExportFileApi();
業務類的導出功能代碼中,沒有和具體的接口對象耦合,根本不知道創建的哪一個接口對象,它只關心得到一個接口對象,再調用接口對象的導出方法,完成數據導出功能。
三、工廠方法的結構
 
Product:定義工廠方法所創建的對象的接口,也就是實際需要使用的對象接口 ExportFileApi
Creator:創建器,聲明工廠方法,工廠方法通常會返回一個Product類的實例對象,而且多是抽象方法。也可以在Creator裏面提供工廠方法的默認實現,讓工廠方法返回一個缺省的Product類型的實例對象 ExportOperate
ConcreteProduct:具體Product接口的實現對象 ExportTxtFile ExportDBFile
ConcreteCreator:具體的創建對象,覆蓋實現Creato定義的工廠方法,返回具體的Product實例 ExportTxtFileOperate ExportDBFileOperate
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章