Java設計模式(三) 抽象工廠模式

来源:http://www.cnblogs.com/jasongj/archive/2016/06/08/5568902.html
-Advertisement-
Play Games

本文介紹了抽象工廠模式的概念,UML類圖,優缺點,實現方式以及(未)遵循的OOP原則。同時結合J2EE中常用的DAO實例詳解了抽象工廠模式的實現。 ...


原創文章,同步發自作者個人博客,轉載請註明出處 http://www.jasongj.com/design_pattern/abstract_factory/

抽象工廠模式解決的問題

上文《工廠方法模式》中提到,在工廠方法模式中一種工廠只能創建一種具體產品。而在抽象工廠模式中一種具體工廠可以創建多個種類的具體產品。

抽象工廠模式

抽象工廠模式介紹

抽象工廠模式(Factory Method Pattern)中,抽象工廠提供一系列創建多個抽象產品的介面,而具體的工廠負責實現具體的產品實例。抽象工廠模式與工廠方法模式最大的區別在於抽象工廠中每個工廠可以創建多個種類的產品。

抽象工廠模式類圖

抽象工廠模式類圖如下 (點擊可查看大圖)

抽象工廠模式角色劃分

  • 抽象產品(或者產品介面),如上文類圖中的IUserDao,IRoleDao,IProductDao
  • 具體產品,如PostgreSQLProductDao
  • 抽象工廠(或者工廠介面),如IFactory
  • 具體工廠,如果MySQLFactory
  • 產品族,如Oracle產品族,包含OracleUserDao,OracleRoleDao,OracleProductDao

抽象工廠模式使用方式

與工廠方法模式類似,在創建具體產品時,客戶端通過實例化具體的工廠類,並調用其創建目標產品的方法創建具體產品類的實例。根據依賴倒置原則,具體工廠類的實例由工廠介面引用,具體產品的實例由產品介面引用。具體調用代碼如下

package com.jasongj.client;

import com.jasongj.bean.Product;
import com.jasongj.bean.User;
import com.jasongj.dao.role.IRoleDao;
import com.jasongj.dao.user.IUserDao;
import com.jasongj.dao.user.product.IProductDao;
import com.jasongj.factory.IDaoFactory;
import com.jasongj.factory.MySQLDaoFactory;

public class Client {

  public static void main(String[] args) {
    IDaoFactory factory = new MySQLDaoFactory();

    IUserDao userDao = factory.createUserDao();
    User user = new User();
    user.setUsername("demo");
    user.setPassword("demo".toCharArray());
    userDao.addUser(user);

    IRoleDao roleDao = factory.createRoleDao();
    roleDao.getRole("admin");

    IProductDao productDao = factory.createProductDao();
    Product product = new Product();
    productDao.removeProduct(product);

  }

}

抽象工廠模式案例解析

本文所述抽象工廠模式示例代碼可從作者Github下載

上例是J2EE開發中常用的DAO(Data Access Object),操作對象(如User和Role,對應於資料庫中表的記錄)需要對應的DAO類。

在實際項目開發中,經常會碰到要求使用其它類型的資料庫,而不希望過多修改已有代碼。因此,需要為每種DAO創建一個DAO介面(如IUserDao,IRoleDao和IProductDao),同時為不同資料庫實現相應的具體類。

調用方依賴於DAO介面而非具體實現(依賴倒置原則),因此切換資料庫時,調用方代碼無需修改。

這些具體的DAO實現類往往不由調用方實例化,從而實現具體DAO的使用方與DAO的構建解耦。實際上,這些DAO類一般由對應的具體工廠類構建。調用方不依賴於具體工廠而是依賴於抽象工廠(依賴倒置原則,又是依賴倒置原則)。

每種具體工廠都能創建多種產品,由同一種工廠創建的產品屬於同一產品族。例如PostgreSQLUserDao,PostgreSQLRoleDao和PostgreSQLProductDao都屬於PostgreSQL這一產品族。

切換資料庫即是切換產品族,只需要切換具體的工廠類。如上文示例代碼中,客戶端使用的MySQL,如果要換用Oracle,只需將MySQLDaoFactory換成OracleDaoFactory即可。

抽象工廠模式優點

  • 因為每個具體工廠類只負責創建產品,沒有簡單工廠中的邏輯判斷,因此符合單一職責原則。
  • 與簡單工廠模式不同,抽象工廠並不使用靜態工廠方法,可以形成基於繼承的等級結構。
  • 新增一個產品族(如上文類圖中的MySQLUserDao,MySQLRoleDao,MySQLProductDao)時,只需要增加相應的具體產品和對應的具體工廠類即可。相比於簡單工廠模式需要修改判斷邏輯而言,抽象工廠模式更符合開-閉原則。

抽象工廠模式缺點

  • 新增產品種類(如上文類圖中的UserDao,RoleDao,ProductDao)時,需要修改工廠介面(或者抽象工廠)及所有具體工廠,此時不符合開-閉原則。抽象工廠模式對於新的產品族符合開-閉原則而對於新的產品種類不符合開-閉原則,這一特性也被稱為開-閉原則的傾斜性。

抽象工廠模式與OOP原則

已遵循的原則

  • 依賴倒置原則(工廠構建產品的方法均返回產品介面而非具體產品,從而使客戶端依賴於產品抽象而非具體)
  • 迪米特法則
  • 里氏替換原則
  • 介面隔離原則
  • 單一職責原則(每個工廠只負責創建自己的具體產品族,沒有簡單工廠中的邏輯判斷)
  • 開閉原則(增加新的產品族,不像簡單工廠那樣需要修改已有的工廠,而只需增加相應的具體工廠類)

未遵循的原則

  • 開閉原則(雖然對新增產品族符合開-閉原則,但對新增產品種類不符合開-閉原則)

Java設計模式系列


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • //資源和認證伺服器不相同http://xxxx:8080/flowAuth/oauth/authorize?client_id=jerry&redirect_uri=http%3a%2f%2fxxxx%3a8080%2fAuthProvider%2ftest%2findex.do&response ...
  • python3+任務計劃實現的人人影視網站自動簽到 這是一個自動化程度較高的程式,運行本程式後會從chrome中讀取cookies用於登錄人人影視簽到, 並且會自動添加一個windows 任務計劃,這個任務計劃每天下午兩點會執行本程式進行簽到。 sys.executable == 'C:\\Pyth ...
  • list 是 Python 中使用最頻繁的數據類型, 標準庫裡面有豐富的函數可以使用。不過,如果把多維列表轉換成一維列表(不知道這種需求多不多),還真不容易找到好用的函數,要知道Ruby、Mathematica、Groovy中可是有flatten的啊。如果列表是維度少的、規則的,還算好辦例如: li ...
  • 其實php開發中的中文編碼並沒有想像的那麼複雜,雖然定位和解決問題沒有定規,各種運行環境也各不盡然,但後面的原理是一樣的。瞭解字元集的知識是解決字元問題的基礎。 PHP程式設計中中文編碼問題曾經困擾很多人,導致這個問題的原因其實很簡單,每個國家(或區域)都規定了電腦信息交換用的字元編碼集,如美國的 ...
  • 一、重載(overload)指函數名相同,但是它的參數表列個數或順序,類型不同。但是不能靠返回類型來判斷。(1)相同的範圍(在同一個作用域中) ;(2)函數名字相同;(3)參數不同;(4)virtual 關鍵字可有可無。(5)返回值可以不同; 二、重寫(也稱為覆蓋 override)是指派生類重新定 ...
  • 1.什麼是JSP內置對象? jsp內置對象就是Web容器創建的一組對象,我們都知道Tomcat可以看成是一種Web容器,所以我們可以知道所謂的內置對象Tomcat創建的,使用內置對象時可以不適用new關鍵字, 直接使用即可. 2.什麼是內置對象? 解析:就是Web容器創建的一組對象,當Tocmat啟 ...
  • 在使用 masonry 框架實現自動佈局時,在程式里為一個佈局穿插著6行左右這樣的代碼 [View mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(anotherView); make.left.equalTo(a ...
  • 參考資料: Python:http://www.runoob.com/python/python-intro.html Python爬蟲系列教程:http://www.cnblogs.com/xin-xin/p/4297852.html 正則表達式:http://www.cnblogs.com/de ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...