手撕设计模式之「简单工厂模式」(Java描述)
前言
利用簡單工廠模式可以實現對象創建和業務邏輯處理的分離,但存在工廠類職責過重,增添新產品違背開閉原則等問題。它不屬于GoF 23種設計模式之一,但是它可以作為學習工廠方法模式前的一個很好的引導。
為了方便學習和交流,我會把「手撕設計模式」系列的代碼上傳到Github,需要的小伙伴可以到上面下載(記得順手star一下~)。
GitHub地址:https://github.com/VeggieOrz/DesignPattern
文章目錄
- 前言
- 1. 模式動機
- 2. 模式定義
- 3.模式結構
- 4. 模式實現
- 5. 模式總結
- 5.1 優點
- 5.2 缺點
- 5.3 適用環境
- 參考資料
1. 模式動機
在這里還是考慮這個很經典的軟件應用場景,一個軟件系統可以提供多個外觀不用的按鈕(如圓形按鈕、矩形按鈕、菱形按鈕等),這些按鈕都源自同一個基類,不過繼承基類后不同的子類修改了部分屬性從而使得它們可以呈現不同的外觀,如果我們希望在使用這些按鈕時,不需要知道這些具體按鈕類的名稱,只需要知道表示該按鈕類的一個參數,并提供一個調用方便的方法,把該參數傳入方法即可返回一個相應的按鈕對象。此時,就可以使用簡單工廠模式。
2. 模式定義
簡單工廠模式(Simple Factory Pattern),又稱為為靜態工廠方法(Static Factory Method)模式,它屬于類創建模式。在簡單工廠模式中,可以根據參數的不同返回不同類的實例。簡單工廠模式專門定義一個類來負責創建其他類的實例,被創建的實例通常都具有共同的父類。
簡單工廠模式的要點:當你需要什么,只需要傳入一個正確的參數,就可以獲取你所需的對象,無需知道其創建細節。
3.模式結構
模式的結構如下圖所示:
簡單工廠模式包含如下角色:
- Factory(工廠角色):工廠類是簡單工廠模式的核心,負責實現創建所有實例的內部邏輯。外界通過調用它提供的靜態工廠方法factoryMethod()來實現對象的創建,需要注意的是,方法的返回類型必須是抽象產品類(接口)。
- Product(抽象產品角色):抽象產品類是簡單工廠模式所有對象的父類,負責描述所有實例所共有的公共接口。
- ConcreteProduct(具體產品角色):具體產品類繼承了抽象產品類,是它的具體實現類(需要實現定義抽象產品類中的抽象方法),也是簡單工廠模式的創建目標。
4. 模式實現
這里就根據上面的模式結構圖,對簡單工廠模式進行一個簡單的實現。
(1)抽象產品類
這是所有產品類的抽象類,它定義了所有產品類所以共有的方法,我們在這里把它定義成接口。
// 抽象產品類 public interface Product {public void use(); }(2)具體產品類
這是具體產品實現類,它繼承(實現)了抽象類(接口),是對抽象產品的具體描述,需要實現在抽象類中定義的方法。
// 具體產品類A public class ConcreteProductA implements Product {public void use() {System.out.println("This is product A");} } // 具體產品類B public class ConcreteProductB implements Product{public void use() {System.out.println("This is product B");} }(3)工廠類
這是工廠類,它提供了負責創建具體產品類對象的靜態工廠方法。需要注意的是,方法的返回值類型必須是抽象產品類。
// 工廠類 public class Factory {// 靜態工廠方法public static Product createProduct(String arg) throws Exception{if (arg != null && "A".equalsIgnoreCase(arg)) {System.out.println("Product A is being produced");return new ConcreteProductA();} else if (arg != null && "B".equalsIgnoreCase(arg)) {System.out.println("Product B is being produced");return new ConcreteProductB();} else {throw new Exception("Sorry,This kind of product is not found");}} }(4)工具類
這是一個用具類,主要用于讀取配置文件。可以幫助客戶端在不需要修改代碼的情況下,完成具體產品類對象的更換。
import java.io.File; import javax.xml.parsers.*; import org.w3c.dom.*;public class XMLUtilProduct {public static String getBrandName() {try {// 創建文檔對象DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();DocumentBuilder builder = dFactory.newDocumentBuilder();Document doc;doc = builder.parse(new File("./src/simpleFactory/configProduct.xml"));// 獲取包含品牌名稱的文本節點NodeList nl = doc.getElementsByTagName("brandName");Node classNode = nl.item(0).getFirstChild();String brandName = classNode.getNodeValue().trim();return brandName;} catch (Exception e) {e.printStackTrace();return null;}} }(5)客戶端
客戶端主要用于對簡單工廠模式的測試,我們只要改變配置文件中<brandName>標簽中的值,就可以實現從具體產品類A到具體產品類B的使用切換,不需要修改任何代碼。
public class Client {public static void main(String[] args) {try {Product product;String brandName = XMLUtilProduct.getBrandName(); product = Factory.createProduct(brandName);product.use();} catch (Exception e) {System.out.println(e.getMessage());}} }配置文件如下所示:
<?xml version="1.0"?> <config><brandName>A</brandName> </config>只要掌握這種實現思想,即使換成其他產品(手機、電視機……),只要滿足簡單工廠方法的使用場景,你就可以它應用到系統的實現中。
5. 模式總結
5.1 優點
- 實現了對象創建和使用的分離。
- 客戶端無須知道所創建的具體產品類的類名,只需要知道產品類所對應的參數即可。
- 通過引入配置文件,可以在不修改客戶端代碼的情況下更換具體產品類,在一定程度上提高了系統的靈活性。
5.2 缺點
- 工廠類的職責過重,它集中了所有產品的創建邏輯,一旦不能正常工作,整個系統都要受到影響。
- 系統拓展困難,一旦添加新產品不得不修改工廠邏輯,違背了開閉原則。
- 工廠類不能得到很好地拓展,由于使用了靜態工廠方法,造成工廠覺得無法形成基于繼承的等級結構。c
5.3 適用環境
- 工廠類負責創建的對象比較少:由于穿件對象較少,不會造成工廠方法中的業務邏輯太過復雜。
- 客戶端只知道傳入工廠類的參數,對于如何創建對象不關系:客戶端既不需要關心創建細節,甚至連類名都不需要記住,只需要知道類型所對應的參數。
參考資料
如果看完本文感覺有所收獲,別忘了點贊哦~
總結
以上是生活随笔為你收集整理的手撕设计模式之「简单工厂模式」(Java描述)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 面试必备算法题集之「动态规划」Ⅰ
- 下一篇: 手撕设计模式之「工厂方法模式」(Java