簡述 類型:創建型 目的:實現對客戶端中對象的平替。 我們藉以下案例來說說如何使用工廠方法模式平替對象。 優化案例 最初版 public interface OS { public void start(); public void sleep(); public void restart(); p ...
簡述
-
類型:創建型
-
目的:實現對客戶端中對象的平替。
我們藉以下案例來說說如何使用工廠方法模式平替對象。
優化案例
最初版
public interface OS {
public void start();
public void sleep();
public void restart();
public void stop();
}
public class Linux implements OS {
public void start() {
System.out.println("啟動Linux系統!");
}
public void sleep() {
System.out.println("睡眠Linux系統!");
}
public void restart() {
System.out.println("重啟Linux系統!");
}
public void stop() {
System.out.println("停止Linux系統!");
}
}
public class Windows implements OS {
public void start() {
System.out.println("啟動Windows系統!");
}
public void sleep() {
System.out.println("睡眠Windows系統!");
}
public void restart() {
System.out.println("重啟Windows系統!");
}
public void stop() {
System.out.println("停止Windows系統!");
}
}
public class Unix implements OS {
public void start() {
System.out.println("啟動Unix系統!");
}
public void sleep() {
System.out.println("睡眠Unix系統!");
}
public void restart() {
System.out.println("重啟Unix系統!");
}
public void stop() {
System.out.println("停止Unix系統!");
}
}
客戶端調用如下。
public class Client {
public static void main(String[] args) {
OS os1 = new Linux();
OS os2 = new Windows();
OS os3 = new Unix();
}
}
傳統是new創建對象的方式有著硬編碼的問題。當我們需要把所有Linux對象改為Unix對象時,就必須在項目中檢索所有的Linux一一修改為Unix。這無疑增加了大量的無意義的工作。
修改版v1(簡單工廠模式)
增加一個工廠類,其他不變。
public class OSFactory {
static OS instance(String arg) {
if (arg.equals("Linux")) {
return new Linux();
} else if (arg.equals("Unix")) {
return new Unix();
} else if (arg.equals("Windows")) {
return new Windows();
}
throw new Exception("輸入的參數錯誤");
}
}
修改後,客戶端的代碼調用。
public class Client {
public static void main(String[] args) {
OS os1 = OSFactory.instance("Linux");
OS os2 = OSFactory.instance("Windows");
OS os3 = OSFactory.instance("Unix");
}
}
在一定程度上解決了客戶端硬編碼問題。並且當我們需要把所有Linux對象改為Unix對象時,只需要在OS中將new Linux() → new Unix()
即可。這無疑節省了很多的時間,也無需為硬編碼帶來的大量改修而苦惱。
但是目前這個優化方案依然有至少兩個問題,一是OSFactory.instance
方法中耦合了所有的OS實現類,這可能有礙於未來的項目維護,二是new Linux() → new Unix()
這種修改方式會導致代碼變得不明確,既然不論是Linux還是Unix都直接生成Unix對象,就沒有必要定義Linux了呀。實際上是因為客戶端代碼中還有使用OSFactory.instance("Linux")
來創建的對象,為了不修改客戶端代碼,強行做如上修改。
修改版v2(工廠方法模式)
將原本的工廠類抽象化,並定義一系列不同的實現類,其餘不變。
public interface OSFactory {
OS create();
}
public class LinuxFactory {
public OS create() {
return new Linux();
}
}
public class WindowsFactory {
public OS create() {
return new Windows();
}
}
public class UnixFactory {
public OS create() {
return new Unix();
}
}
修改後,客戶端的代碼調用。
public class Client {
public static void main(String[] args) {
OSFactory factory = new LinuxFactory();
OS os1 = factory.create();
}
}
將原本OSFactory
類中臃腫的邏輯分散到各個子類中,提高了系統的可維護性,不用再每次都修改Factory類了。
那麼,問題來了,這樣的結構對於我們的項目有什麼幫助嗎?幾乎沒有,我們只是將對象的創建統一管理了而已,這也只是工廠方法模式的一個很小的功能。實際上需求是快速的將系統中的對象平替。而為了實現這個需求,我們需要結合Java反射這項技術。請看下麵的代碼。
修改版v3(工廠方法+反射)
只修改客戶端的調用方式,其他位置不做修改。
public class Client {
public static void main(String[] args) {
// 實際項目中一般定義成特定的類(專門用來載入各種配置)中的靜態變數
Properties prop = new Properties();
FileReader fileReader = new FileReader("src/resource/props/config.prop");
// 使用properties文件來存儲當前調用類的信息
prop.load(fileReader);
fileReader.close();
OSFactory factory = (OSFactory) Class.forName(prop.getProperty("FACTORY"))
.getDeclaredConstructor().newInstance();
OS os1 = factory.create();
}
}
增加一個properties文件文件,定義如下。
#當前使用的工廠類
FACTORY=design.factorymethod.demo02.LinuxFactory
當系統需要將實例的LinuxFactory
類轉化為其他的實現類時,只需要更改上述配置文件即可。
總結
優點
- 輕鬆做到類的平替。
缺點
- 類數量倍增,系統複雜度增加。
應用場景
- 根據需求,需要全面替換系統中的某個類時。
本文來自博客園,作者:buzuweiqi,轉載請註明原文鏈接:https://www.cnblogs.com/buzuweiqi/p/16703315.html