型別:建立型
目的:實現對使用者端中物件的平替。
我們藉以下案例來說說如何使用工廠方法模式平替物件。
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。這無疑增加了大量的無意義的工作。
增加一個工廠類,其他不變。
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")
來建立的物件,為了不修改使用者端程式碼,強行做如上修改。
將原本的工廠類抽象化,並定義一系列不同的實現類,其餘不變。
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反射這項技術。請看下面的程式碼。
只修改使用者端的呼叫方式,其他位置不做修改。
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