Spring Boot中使用注解實現簡單工廠模式


前言

  從設計模式的類型上來說,簡單工廠模式是屬於創建型模式,又叫靜態工廠模式(Simple Factory Pattern),但不屬於23種GOF設計模式之一。簡單工廠模式是由一個工廠對象決定創建出接口哪一種實現類的實例。簡單工廠模式是工廠模式家族中最簡單實用的模式,可以理解為是不同工廠模式的一個特殊實現。 

  在簡單工廠模式中,可以根據參數的不同返回不同類的實例。簡單工廠模式專門定義一個類來負責創建其他類的實例,被創建的實例通常都具有共同的父類。

  簡單工廠模式只需要向工廠類傳入一個正確的參數,就可以獲取所需要的對象,而無需知道其實現過程。

  簡單工廠模式是在什么場景下使用呢?這里簡單的枚舉幾個使用場景:

1、日志記錄器:記錄可能記錄到本地硬盤、系統事件、遠程服務器等,用戶可以選擇記錄日志到什么地方;

2、保險產品配置:保險產品往往有很多賠付等級,每個等級對應不同的保額和賠付金額;

3、設計一個連接服務器的框架,需要三個協議,"POP3"、"IMAP"、"HTTP",可以把這三個作為產品類,共同實現一個接口。

 定義中最重要的一句話就是,由一個工廠對象決定創建出哪一種實現類的實例。在文章《Spring注解之@Autowired:注入Arrays, Collections, and Maps》中,小編介紹了Spring Boot如何把某些接口實現類的Bean注入到Map和List等集合中,方便應用的時候直接讀取需要的bean。結合@Autowired可以自動注入指定接口實現類到Map中,介紹簡單工廠模式的一個實現策略。

簡單工廠模式實踐

  我們將創建一個 Shape 接口和實現 Shape 接口的實體類。下一步是定義工廠類 ShapeFactory。在controller FactoryPatternDemo 中,我們演示使用 ShapeFactory 來獲取 Shape 對象。它將向 ShapeFactory 傳遞信息(circle/rectangle/square),以便獲取它所需對象的類型。

   新增接口類Shape:

/** * 定義bean接口 */
public interface Shape { void draw(); }

   創建Shape的三個實現類,並且都添加注解@Service,將其注冊為Spring Bean。

@Service public class Rectangle implements Shape { @Override public void draw() { System.out.println("Inside Rectangle::draw() method."); } } =========== 我是分割線 ============= @Service public class Square implements Shape { @Override public void draw() { System.out.println("Inside Square::draw() method."); } } =========== 我是分割線 ============= @Service public class Circle implements Shape { @Override public void draw() { System.out.println("Inside Circle::draw() method."); } }

 實現方法一:基於新建對象實現

  茲創建一個工廠類,根據調用者的不同,創建不同的實現類並返回。而如果碰到不合法的請求參數,則會返回null。 

/** * 簡單工廠類,通過新建對象實現 * 不添加Spring注解,調用的時候直接new */
public class ShapeFactory { /** * 使用 getShape 方法獲取幾何圖形類型的對象 */
    public static Shape getShape(String shapeType) { if ("circle".equalsIgnoreCase(shapeType)) { return new Circle(); } else if ("rectangle".equalsIgnoreCase(shapeType)) { return new Rectangle(); } else if ("square".equalsIgnoreCase(shapeType)) { return new Square(); } return null; } }

 實現方法二:基於spring注解實現

  下面新增一個類ShapeBeanFactory,通過@Autowired注解把bean注入map后,由變量map替換工廠類,實現簡單工廠模式。

/** * 簡單工廠類,通過 Spring注解 @Autowired 和 @Service 實現 */ @Component // 添加Spring注解
public class ShapeBeanFactory { @Autowired private Map<String, Shape> shapeMap; public Shape getShape(String shapeType) { Shape bean1 = shapeMap.get(shapeType); System.out.println(bean1); return bean1; } }

   通過對比兩種實現方案可以發現,使用Spring注解的方式更加簡潔,避開了 if else 分支。 

客戶端調用工廠類

 創建一個controller,命名為FactoryPatternDemo,並把兩種實現方案封裝為不同的私有方法。客戶端調用工廠類,傳入幾何圖形類型參數獲取幾何圖形對象並調用該對象的draw方法:

 @GetMapping("/drawMyShape") public String drawMyShape(){ shapeFactoryDraw(); shapeBeanFactoryDraw(); return "成功"; } private void shapeFactoryDraw() { System.out.println("======= shapeFactory ======="); //獲取 Circle 的對象,並調用它的 draw 方法
        Shape shapeInterface1 = ShapeFactory.getShape("circle"); //調用 Circle 的 draw 方法
 shapeInterface1.draw(); Shape shapeInterface2 = ShapeFactory.getShape("rectangle"); shapeInterface2.draw(); } @Autowired private ShapeBeanFactory factory; // 使用注解注入

    private void shapeBeanFactoryDraw() { System.out.println("======= 實現二 shapeBeanFactory ======="); Shape shapeInterface1 = factory.getShape("circle"); shapeInterface1.draw(); Shape shapeInterface2 = factory.getShape("square"); shapeInterface2.draw(); }

     客戶端請求draw函數,控制台輸出結果如下,說明對工廠類重構成功。

======= shapeFactory ======= Inside Circle::draw() method. Inside Rectangle::draw() method. ======= 實現二 shapeBeanFactory ======= com.eg.wiener.service.impl.shape.Circle@3a0aa6f6 Inside Circle::draw() method. com.eg.wiener.service.impl.shape.Square@6d48c8f9 Inside Square::draw() method.

 

優缺點和適用場景

 

優點

   工廠類是整個模式的關鍵。包含了必要的邏輯判斷,根據外界給定的信息,決定究竟應該創建哪個具體類的對象。通過使用工廠類,外界可以從直接創建具體產品對象的尷尬局面擺脫出來,僅僅需要負責“消費”對象就可以了,而不必管這些對象究竟如何創建及如何組織的,只需要知道具體產品類所對應的參數即可,對於一些復雜的類名,通過簡單工廠模式可以減少使用者的記憶量。明確了各自的職責和權利,有利於整個軟件體系結構的優化。

   通過引入配置文件,可以在不修改任何客戶端代碼的情況下更換和增加新的具體產品類,在一定程度上提高了系統的靈活性。

缺點

   由於工廠類集中了所有實例的創建邏輯,違反了高內聚責任分配原則,將全部創建邏輯集中到了一個工廠類中;它所能創建的類只能是事先考慮到的,如果需要添加新的類,則就需要改變工廠類了。

   當系統中的具體產品類不斷增多時候,可能會出現要求工廠類根據不同條件創建不同實例的需求。這種對條件和具體產品類型的判斷交錯在一起,很難避免模塊功能的蔓延,對系統的維護和擴展非常不利;

   違背開閉原則。對於上面兩種簡單工廠模式的實現方法,如果我們要添加新的 幾何圖形,勢必要改動 ShapeFactory的代碼,那這是不是違反開閉原則呢?實際上,如果不需要頻繁地添加新的幾何圖形實現類,只是偶爾修改一下代碼,稍微不符合開閉原則,但權衡擴展性和可讀性,這樣的代碼實現在大多數情況下,也是可以接受的。這是第一種實現方案的瑕疵,但是,第二種實現方案就沒有違背開閉原則,完全由Spring IOC容器管理Bean,彰顯了Spring IOC容器的強大之處。

適用場景

   在以下場景適合使用簡單工廠模式:

   工廠類負責創建的對象比較少:由於創建的對象較少,不會造成工廠方法中的業務邏輯太過復雜。

客戶端只知道傳入創建工廠類所需的參數,對於如何創建對象不關心:客戶端既不需要關心創建細節,甚至連類名都不需要記住,只需要知道類型所對應的參數。 

Reference

https://www.runoob.com/design-pattern/factory-pattern.html

http://www.cnblogs.com/java-my-life/archive/2012/03/22/2412308.html

https://www.jianshu.com/p/5cb52d84bd6d

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM