1.複合開閉原則,對擴充套件開放,對修改關閉。客戶端比如feign呼叫時,當服務端修改程式碼後,客戶端不需要修改程式碼。
Java中的工廠方法模式(Factory Method Pattern)是一種建立型設計模式,它提供了一種建立物件的最佳方式。以下是對Java工廠方法模式的詳細解析:
一、定義與特點
工廠方法模式定義了一個用於建立物件的介面,但讓子類決定要例項化的類是哪一個。工廠方法讓類的例項化推遲到子類中進行。其主要特點包括:
- 抽象工廠角色:宣告瞭工廠方法,用於返回一個產品物件。
- 具體工廠角色:實現了抽象工廠角色中的工廠方法,用於返回一個具體的產品物件。
- 抽象產品角色:定義了產品的介面,是工廠方法所建立物件的超型別,也就是產品物件的共同介面。
- 具體產品角色:實現了抽象產品角色所定義的介面,由具體工廠角色建立,客戶端透過抽象產品角色使用具體產品。
二、結構與實現
工廠方法模式的典型結構包含以下四個主要部分:
- 抽象產品類:定義產品的介面,是工廠方法所建立的物件的超型別,即產品物件的共同介面。
- 具體產品類:實現了抽象產品類所定義的介面,由具體工廠類建立,客戶端透過抽象產品類使用具體產品。
- 抽象工廠類:宣告瞭工廠方法,用於返回一個產品物件。它是一個抽象類,通常由Java介面或抽象類實現。
- 具體工廠類:實現了抽象工廠類中的工廠方法,用於建立一個具體的產品物件。
在實現時,客戶端程式碼透過抽象工廠類和抽象產品類與具體實現進行解耦,從而可以在不修改客戶端程式碼的情況下更換具體工廠類或具體產品類。
三、優點
- 降低耦合度:透過將物件的建立過程集中到一個工廠類中,降低了客戶端與具體產品之間的耦合度,使得系統更加靈活和易於維護。
- 提高複用性:工廠方法模式透過工廠方法、抽象工廠等方式來建立物件,提高了程式碼的複用性和可讀性。它避免了重複的程式碼實現,因為物件的建立邏輯被封裝在工廠類中,可以在多個地方重用該工廠類的例項或方法。
- 符合開閉原則:工廠方法模式支援在不修改已有程式碼的前提下擴充套件系統,透過新增新的具體工廠類和具體產品類來實現新的功能。
- 隱藏建立細節:工廠方法模式將物件的建立過程封裝在工廠類中,對客戶端隱藏了物件的建立細節,增強了系統的安全性。
四、缺點
- 增加系統複雜性:每增加一個產品,都需要增加一個具體產品類和一個具體工廠類,增加了系統的複雜性。當產品種類較多時,會導致類的數量激增。
- 產品族擴充套件困難:在工廠方法模式中,如果需要增加新的產品族(即一組相關聯的產品),需要修改所有的具體工廠類,這在一定程度上影響了系統的擴充套件性。
五、適用場景
- 當一個類不知道它所必須建立的物件的類時。
- 當一個類希望由它的子類來指定它所建立的物件時。
- 當類將建立物件的職責委託給多個幫助子類中的某一個,並且你希望將哪一個幫助子類是代理者這一資訊區域性化時。
六、示例程式碼
以下是一個簡單的工廠方法模式示例程式碼:
// 抽象產品角色 | |
public interface Product { | |
void doSomething(); | |
} | |
// 具體產品A | |
public class ProductA implements Product { | |
public void doSomething() { | |
System.out.println("A do Something"); | |
} | |
} | |
// 具體產品B | |
public class ProductB implements Product { | |
public void doSomething() { | |
System.out.println("B do Something"); | |
} | |
} | |
// 抽象工廠角色 | |
public abstract class Factory { | |
abstract Product create(); | |
} | |
// 具體工廠A | |
public class FactoryA extends Factory { | |
Product create() { | |
return new ProductA(); | |
} | |
} | |
// 具體工廠B | |
public class FactoryB extends Factory { | |
Product create() { | |
return new ProductB(); | |
} | |
} | |
// 客戶端程式碼 | |
public class Client { | |
public static void main(String[] args) { | |
Factory factory = new FactoryA(); | |
Product product = factory.create(); | |
product.doSomething(); | |
factory = new FactoryB(); | |
product = factory.create(); | |
product.doSomething(); | |
} | |
} |
在這個示例中,Product
是抽象產品角色,ProductA
和ProductB
是具體產品角色,Factory
是抽象工廠角色,FactoryA
和FactoryB
是具體工廠角色。客戶端程式碼透過呼叫具體工廠類的create
方法來建立具體的產品物件,並呼叫產品的doSomething
方法。
綜上所述,Java工廠方法模式是一種強大的設計工具,可以幫助開發者構建更加靈活、可擴充套件和易於維護的軟體系統。透過合理地使用工廠方法模式,可以提高程式碼的質量、可維護性和可複用性。
如果不使用工廠方法模式建立物件,而是手動建立,程式碼的結構會相對簡單,但可能會失去工廠方法模式帶來的靈活性和可擴充套件性。以下是一個不使用工廠方法模式,而是直接手動建立物件的示例程式碼:
// 產品介面或抽象類 | |
public interface Product { | |
void doSomething(); | |
} | |
// 具體產品A | |
public class ProductA implements Product { | |
public void doSomething() { | |
System.out.println("ProductA is doing something."); | |
} | |
} | |
// 具體產品B | |
public class ProductB implements Product { | |
public void doSomething() { | |
System.out.println("ProductB is doing something."); | |
} | |
} | |
// 客戶端程式碼 | |
public class Client { | |
public static void main(String[] args) { | |
// 手動建立ProductA物件 | |
Product productA = new ProductA(); | |
productA.doSomething(); | |
// 手動建立ProductB物件 | |
Product productB = new ProductB(); | |
productB.doSomething(); | |
// 如果需要更多的產品型別,繼續手動建立 | |
// ... | |
} | |
} |
在這個示例中,Product
介面定義了一個產品應該具有的行為,ProductA
和ProductB
是實現了該介面的具體產品。客戶端程式碼Client
中直接使用了new
關鍵字來建立ProductA
和ProductB
的例項,並呼叫了它們的方法。
與工廠方法模式相比,這種手動建立物件的方式有以下幾個缺點:
-
程式碼耦合度高:客戶端程式碼直接依賴於具體的產品類,如果產品類發生變化(比如類名、包名或構造方法),客戶端程式碼也需要相應地進行修改。
-
擴充套件性差:如果系統中需要新增新的產品型別,客戶端程式碼需要修改以包含新的產品建立邏輯,這違反了開閉原則(對擴充套件開放,對修改關閉)。
-
缺乏靈活性:客戶端程式碼在編譯時就確定了要建立的物件型別,無法在執行時動態地選擇建立哪種型別的產品。
因此,雖然手動建立物件的方式在程式碼上看起來更簡單,但在大型系統中,使用工廠方法模式或其他建立型設計模式通常能夠帶來更好的程式碼結構、更高的靈活性和可擴充套件性。