簡單工廠模式-設計模式
定義
簡單工廠模式(Simple Factory Pattern):定義一個工廠類,它可以根據引數的不同返回不同類的例項,被建立的例項通常都具有共同的父類。因為在簡單工廠模式中用於建立例項的方法是靜態(static)方法,因此簡單工廠模式又被稱為靜態工廠方法(Static Factory Method)模式,它屬於類建立型模式。
1.簡單工廠模式提供了專門的工廠類用於建立物件,將物件的建立和物件的使用分離開,它作為一種最簡單的工廠模式在軟體開發中得到了較為廣泛的應用;
2.簡單工廠模式是工廠方法模式的“小弟”,它不屬於23種設計模式,但在軟體開發中應用也較為頻繁,通常將它作為學習其他工廠模式的入門;
3.簡單工廠模式的要點在於:當你需要什麼,只需要傳入一個正確的引數,就可以獲取你所需要的物件,而無須知道其建立細節。
簡介
應用例項
1.您需要一輛汽車,可以直接從工廠裡面提貨,而不用去管這輛汽車是怎麼做出來的,以及這個汽車裡面的具體實現; 2.Hibernate 換資料庫只需換方言和驅動就可以。
使用場景
1.工廠類負責建立的物件比較少,由於建立的物件較少,不會造成工廠方法中的業務邏輯太過複雜; 2. 客戶端只知道傳入工廠類的引數,對於如何建立物件並不關心。
實現:圖示庫設計
公司欲基於Java語言開發一套圖表庫,該圖表庫可以為應用系統提供各種不同外觀的圖表,例如柱狀圖、餅狀圖、折線圖等。設計人員希望為應用系統開發人員提供一套靈活易用的圖表庫,而且可以較為方便地對圖表庫進行擴充套件,以便能夠在將來增加一些新型別的圖表。
方案一
class Chart {
private String type; //圖表型別
public Chart(String type) {
this.type = type;
if (type.equalsIgnoreCase("histogram")) {
System.out.println("初始化柱狀圖!");
}
else if (type.equalsIgnoreCase("pie")) {
System.out.println("初始化餅狀圖!");
}
else if (type.equalsIgnoreCase ("line")) {
System.out.println("初始化折線圖!");
}
}
public void display() {
if (this.type.equalsIgnoreCase("histogram")) {
System.out.println("顯示柱狀圖!");
}
else if (this.type.equalsIgnoreCase("pie")) {
System.out.println("顯示餅狀圖!");
}
else if (this.type.equalsIgnoreCase("line")) {
System.out.println("顯示折線圖!");
}
}
}
分析以上程式碼:
1:程式碼“if else”程式碼塊很多,程式碼冗長,如果再多幾種型別,閱讀、維護、測試難度就會越複雜。
2:程式碼集中,職責過重,違反了“單一職責原則”,不利於重用、維護和擴充套件。
3:在擴充套件的時候必須修改Chart類,違反了“開閉原則”。
4.客戶端只能通過new關鍵字來直接建立Chart物件,Chart類與客戶端類耦合度較高,物件的建立和使用無法分離。
5.客戶端在建立Chart物件之前可能還需要進行大量初始化設定,例如設定柱狀圖的顏色、高度等,如果在Chart類的建構函式中沒有提供一個預設設定,那就只能由客戶端來完成初始設定,這些程式碼在每次建立Chart物件時都會出現,導致程式碼的重複。
方案二(使用簡單工廠模式)
為了將Chart類的職責分離,同時將Chart物件的建立和使用分離,重新對程式碼進行了重構。
建立圖表介面
public interface Chart {
/**
* 展示圖表
*/
void display();
}
建立圖表工廠
public class ChartFactory {
//靜態工廠方法
public static Chart getChart(String type) {
Chart chart = null;
if (type.equalsIgnoreCase("histogram")) {
chart = new HistogramChart();
System.out.println("初始化設定柱狀圖!");
} else if (type.equalsIgnoreCase("pie")) {
chart = new PieChart();
System.out.println("初始化設定餅狀圖!");
} else if (type.equalsIgnoreCase("line")) {
chart = new LineChart();
System.out.println("初始化設定折線圖!");
}
return chart;
}
}
建立實現類
public class HistogramChart implements Chart {
public HistogramChart() {
System.out.println("建立柱狀圖!");
}
public void display() {
System.out.println("顯示柱狀圖!");
}
}
public class LineChart implements Chart {
public LineChart() {
System.out.println("建立折線圖!");
}
public void display() {
System.out.println("顯示折線圖!");
}
}
public class PieChart implements Chart {
public PieChart() {
System.out.println("建立餅狀圖!");
}
public void display() {
System.out.println("顯示餅狀圖!");
}
}
測試程式碼
public class Main {
public final static String CHART_HISTOGRAM = "histogram";
public final static String CHART_PIE = "pie";
public final static String CHART_LINE = "line";
public static void main(String[] args) {
//通過靜態工廠方法建立產品
Chart chartHistogram = ChartFactory.getChart(CHART_HISTOGRAM);
chartHistogram.display();
Chart chartPie = ChartFactory.getChart(CHART_PIE);
chartPie.display();
Chart chartLine = ChartFactory.getChart(CHART_LINE);
chartLine.display();
}
}
輸出如下
建立柱狀圖!
初始化設定柱狀圖!
顯示柱狀圖!
建立餅狀圖!
初始化設定餅狀圖!
顯示餅狀圖!
建立折線圖!
初始化設定折線圖!
顯示折線圖!
分析以上程式碼:在測試類中,我們使用工廠類的靜態方法來建立物件,如果需要更換其他圖表,只需要修改引數即可。
改進:上述程式碼還存在一個問題,在每次客戶端更換靜態工廠中的引數時,客戶端程式碼都需要重新編譯,對客戶端而言,違反了“開閉原則”,怎麼能在修改引數時不需要修改客戶端程式碼呢? 我們只需要引數放入配置檔案即可。如果需要修改具體圖表引數,只需要修改配置檔案,無需修改任何原始碼,符合“開閉原則”。
總結
優點
1.一個呼叫者想建立一個物件,只要知道其名稱就可以了;
2.擴充套件性高,如果想增加一個產品,只要擴充套件一個工廠類就可以;
3.遮蔽產品的具體實現,呼叫者只關心產品的介面;
4.實現了物件建立和使用分離;
5.通過引入配置檔案,可以在不修改任何客戶端程式碼的情況下更換和增加新的具體產品類,在一定程度上提高了系統的靈活性。
缺點
1.由於工廠類集中了所有產品的建立邏輯,職責過重,一旦不能正常工作,整個系統都要受到影響;
2.每次增加一個產品時,都需要增加一個具體類和物件實現工廠,使得系統中類的個數成倍增加,在一定程度上增加了系統的複雜度,同時也增加了系統具體類的依賴;
3.簡單工廠模式由於使用了靜態工廠方法,造成工廠角色無法形成基於繼承的等級結構。
感謝您的閱讀,如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕。本文歡迎各位轉載,但是轉載文章之後必須在文章開頭給出原文連結。