文章目錄
- 簡單工廠模式示例
- 示例1:電視機工廠
- 示例2:圖表庫工廠
- 在JDK中的應用:`java.util.Calendar`
簡單工廠模式示例
示例1:電視機工廠
接續上一節的電視機場景,我們來看一個完整的代碼實現。
- 代碼實現:
// 角色1: 抽象產品 (Product)
// 定義電視機的通用行為:播放
interface Product {
public void play();
}
// 角色2: 具體產品A (ConcreteProductA)
// 海爾電視機
class ConcreteProductA implements Product {
@Override
public void play() {
System.out.println("海爾電視機播放中......");
}
}
// 角色2: 具體產品B (ConcreteProductB)
// 海信電視機
class ConcreteProductB implements Product {
@Override
public void play() {
System.out.println("海信電視機播放中......");
}
}
// 角色3: 工廠類 (Factory)
class Factory {
// 提供生產產品的靜態方法
public static Product produce(String brand) throws Exception {
if (brand.equalsIgnoreCase("Haier")) {
System.out.println("電視機工廠生產海爾電視機!");
return new ConcreteProductA();
} else if (brand.equalsIgnoreCase("Hisense")) {
System.out.println("電視機工廠生產海信電視機!");
return new ConcreteProductB();
} else {
// 對於無法生產的品牌,拋出異常
throw new Exception("對不起,暫不能生產該品牌電視機!");
}
}
}
- 客户端調用:
// 測試類 (客户端)
public class SimpleFactory {
public static void main(String[] args) {
try {
// 客户端向工廠請求產品,只需要提供品牌名
Product tv = Factory.produce("Haier");
// 客户端直接使用產品,無需關心其具體類型和創建過程
tv.play();
// 更換品牌也只需修改參數
// Product tv2 = Factory.produce("Hisense");
// tv2.play();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
- 運行效果:
電視機工廠生產海爾電視機!
海爾電視機播放中......
示例2:圖表庫工廠
- 背景需求:
- Sunny軟件公司要開發一套圖表庫,提供柱狀圖、餅狀圖、折線圖等不同外觀的圖表。
- 設計目標是為應用系統開發者提供一套靈活易用的圖表庫,並且可以較為方便地對圖表庫進行擴展,以便將來增加新類型的圖表。
- 初始設計 (反面教材):
- 最初,可能將所有圖表的創建和顯示邏輯都耦合在一個
Chart類中。
// 違反單一職責和開閉原則的設計
public class Chart {
private String type; // 圖表類型
// 構造函數中根據類型進行不同的初始化
public Chart(Object[][] data, String type) {
this.type = type;
if (type.equalsIgnoreCase("histogram")) {
// 初始化柱狀圖
} else if (type.equalsIgnoreCase("pie")) {
// 初始化餅狀圖
} else if (type.equalsIgnoreCase("line")) {
// 初始化折線圖
}
}
// 顯示方法中根據類型進行不同的顯示
public void display() {
if (this.type.equalsIgnoreCase("histogram")) {
// 顯示柱狀圖
} else if (this.type.equalsIgnoreCase("pie")) {
// 顯示餅狀圖
} else if (this.type.equalsIgnoreCase("line")) {
// 顯示折線圖
}
}
}
- 問題分析: 這個
Chart類職責過重,既負責創建(初始化)又負責顯示。而且,每當需要增加一種新的圖表類型時,都必須修改這個類的構造函數和display方法,違反了開閉原則。
- 使用簡單工廠模式重構:
- 模式角色分析:
- 抽象產品 (Product):
Chart接口,定義所有圖表都必須具備的display()方法。 - 具體產品 (ConcreteProduct):
HistogramChart,PieChart,LineChart等類,分別實現Chart接口,負責各自圖表的具體顯示邏輯。 - 工廠 (Factory):
ChartFactory類,提供一個靜態方法getChart(String type),根據傳入的類型字符串創建並返回具體的圖表對象。
- 重構後代碼實現:
// 抽象產品:Chart接口
public interface Chart {
public void display();
}
// 具體產品:HistogramChart, PieChart, LineChart 類(代碼略,各自實現display方法)
// 工廠類:ChartFactory
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;
}
}
- 客户端調用:
class Client {
public static void main(String[] args) {
Chart chart;
// 客户端通過工廠獲取實例,實現了創建和使用的分離
chart = ChartFactory.getChart("line");
chart.display(); // 調用產品的功能
}
}
- 運行效果:
初始化設置折線圖!
顯示折線圖!
在JDK中的應用:java.util.Calendar
簡單工廠模式(靜態工廠方法)在Java的JDK源碼中也有廣泛應用。一個典型的例子就是java.util.Calendar類。
- 源碼分析:
- 我們獲取
Calendar實例時,並不是通過new Calendar()(Calendar是抽象類,無法直接new),而是通過調用它的靜態方法Calendar.getInstance()。
import java.util.Calendar;
public class Factory {
public static void main(String[] args) {
// getInstance() 就是一個靜態工廠方法
Calendar cal = Calendar.getInstance();
System.out.println("年: " + cal.get(Calendar.YEAR));
// 月份從0開始,需要+1
System.out.println("月: " + (cal.get(Calendar.MONTH) + 1));
System.out.println("日: " + cal.get(Calendar.DAY_OF_MONTH));
}
}
- 內部機制:
getInstance()方法會根據系統當前的區域設置(Locale)和時區(TimeZone)等信息,在內部決定具體創建並返回哪一個Calendar的子類實例(例如,在大多數情況下是GregorianCalendar)。- 這樣,客户端代碼完全不需要關心底層具體使用的是哪種日曆實現,只需要與
Calendar這個抽象類進行交互即可。這極大地提高了代碼的靈活性和可維護性。
本文章為轉載內容,我們尊重原作者對文章享有的著作權。如有內容錯誤或侵權問題,歡迎原作者聯繫我們進行內容更正或刪除文章。