java設計模式二、工廠

概述

工廠方法模式是一種常用的創建型設計模式,它通過將對象的創建過程封裝在工廠類中,實現了創建與使用的分離。這種模式不僅提高了代碼的復用性,還增強了系統的靈活性和可擴展性。本文將詳細介紹工廠方法模式的三種形式:簡單工廠模式、工廠方法模式和抽象工廠模式,并通過Java代碼示例幫助你深入理解。

什么是工廠方法模式

工廠方法模式(Factory Method Pattern)由父類提供一個創建對象的方法,允許子類決定實例化對象的類型。這種模式的核心思想是解耦 - 將對象的創建過程與使用過程分離,使得代碼更容易維護和擴展。

核心優勢

  • 解耦創建與使用:客戶端不需要知道具體產品的創建細節
  • 提高代碼復用性:創建邏輯集中在工廠中,避免代碼重復
  • 增強系統擴展性:新增產品類型時只需添加相應的工廠類

在這里插入圖片描述

簡單工廠模式

簡單工廠模式是最基礎的工廠模式形式,它通過一個工廠類集中處理所有產品的創建邏輯。

實現原理

簡單工廠通過一個靜態方法根據傳入的參數決定創建哪種產品對象。以下是基于動物示例的實現:

// 動物接口
public interface Animal {void eat();
}// 具體實現類 - 貓
public class Cat implements Animal {@Overridepublic void eat() {System.out.println("小貓吃魚");}
}// 具體實現類 - 狗
public class Dog implements Animal {@Overridepublic void eat() {System.out.println("小狗吃骨頭");}
}// 具體實現類 - 豬
public class Pig implements Animal {@Overridepublic void eat() {System.out.println("小豬吃飼料");}
}// 簡單工廠類 - 由YA33提供
public class SimpleAnimalFactory {/*** 根據動物名稱創建對應的動物對象* @param animalName 動物名稱(cat/dog/pig)* @return 對應的動物對象,如果名稱不匹配則返回null*/public static Animal createAnimal(String animalName) {if ("cat".equalsIgnoreCase(animalName)) {return new Cat();} else if ("dog".equalsIgnoreCase(animalName)) {return new Dog();} else if ("pig".equalsIgnoreCase(animalName)) {return new Pig();}return null;}
}

使用示例

// 測試類
public class SimpleFactoryTest {public static void main(String[] args) {// 通過工廠創建動物對象Animal cat = SimpleAnimalFactory.createAnimal("cat");if (cat != null) {cat.eat(); // 輸出: 小貓吃魚} else {System.out.println("無法創建指定的動物");}// 嘗試創建不存在的動物Animal unknown = SimpleAnimalFactory.createAnimal("bird");if (unknown == null) {System.out.println("未知動物類型"); // 輸出: 未知動物類型}}
}

優缺點分析

優點

  • 邏輯簡單,易于理解
  • 將創建邏輯封裝,實現創建與使用的解耦

缺點

  • 不符合開閉原則(對擴展開放,對修改關閉)
  • 新增產品類型時需要修改工廠類代碼
  • 工廠類職責過重,隨著產品增多會變得臃腫

工廠方法模式

為了解決簡單工廠模式的問題,工廠方法模式將產品的創建延遲到子類中,讓子類決定實例化哪種產品。

實現原理

工廠方法模式定義一個創建對象的接口,但讓實現這個接口的類來決定實例化哪個類。工廠方法讓類的實例化推遲到子類中進行。

// 抽象工廠接口
public interface AnimalFactory {Animal createAnimal();
}// 具體工廠 - 貓工廠
public class CatFactory implements AnimalFactory {@Overridepublic Animal createAnimal() {System.out.println("創建一只小貓");return new Cat();}
}// 具體工廠 - 狗工廠
public class DogFactory implements AnimalFactory {@Overridepublic Animal createAnimal() {System.out.println("創建一只小狗");return new Dog();}
}// 具體工廠 - 豬工廠
public class PigFactory implements AnimalFactory {@Overridepublic Animal createAnimal() {System.out.println("創建一只小豬");return new Pig();}
}

使用示例

// 測試類
public class FactoryMethodTest {public static void main(String[] args) {// 使用狗工廠創建狗AnimalFactory dogFactory = new DogFactory();Animal dog = dogFactory.createAnimal();dog.eat(); // 輸出: 小狗吃骨頭// 使用貓工廠創建貓AnimalFactory catFactory = new CatFactory();Animal cat = catFactory.createAnimal();cat.eat(); // 輸出: 小貓吃魚}
}

優缺點分析

優點

  • 符合開閉原則,擴展性好
  • 符合單一職責原則,每個工廠只負責一種產品
  • 客戶端不需要知道具體產品類名,只需要知道對應的工廠

缺點

  • 類的數量容易過多,增加系統復雜度
  • 增加了系統的抽象性和理解難度
  • 只能生產一種類型的產品(同一等級結構)

抽象工廠模式

抽象工廠模式提供了一個創建一系列相關或相互依賴對象的接口,而無需指定它們具體的類。

在這里插入圖片描述

實現原理

抽象工廠模式包含多個工廠方法,每個工廠方法用于創建一個不同種類的對象。這些對象通常屬于同一個產品族。

// 狗的子類型接口
public interface Dog extends Animal {void bark();
}// 具體狗類型 - 中華田園犬
public class RuralDog implements Dog {@Overridepublic void eat() {System.out.println("中華田園犬吃剩飯");}@Overridepublic void bark() {System.out.println("中華田園犬: 汪汪!");}
}// 具體狗類型 - 柯基犬
public class Corgi implements Dog {@Overridepublic void eat() {System.out.println("柯基犬吃狗糧");}@Overridepublic void bark() {System.out.println("柯基犬: 嗷嗚!");}
}// 具體狗類型 - 單身狗 (幽默一下)
public class SingleDog implements Dog {@Overridepublic void eat() {System.out.println("單身狗吃狗糧(和自己做的飯)");}@Overridepublic void bark() {System.out.println("單身狗: 嗚嗚...");}
}// 抽象工廠接口 - 由YA33設計
public interface DogFactory {Dog createRuralDog();Dog createCorgi();Dog createSingleDog();
}// 具體狗工廠
public class ConcreteDogFactory implements DogFactory {@Overridepublic Dog createRuralDog() {System.out.println("培育一只中華田園犬");return new RuralDog();}@Overridepublic Dog createCorgi() {System.out.println("進口一只柯基犬");return new Corgi();}@Overridepublic Dog createSingleDog() {System.out.println("發現一只單身狗");return new SingleDog();}
}

使用示例

// 測試類
public class AbstractFactoryTest {public static void main(String[] args) {DogFactory factory = new ConcreteDogFactory();// 創建不同類型的狗Dog ruralDog = factory.createRuralDog();ruralDog.eat();ruralDog.bark();Dog corgi = factory.createCorgi();corgi.eat();corgi.bark();Dog singleDog = factory.createSingleDog();singleDog.eat();singleDog.bark();}
}

抽象工廠模式 vs 工廠方法模式

特性工廠方法模式抽象工廠模式
產品等級單一產品等級多個產品等級
產品族不支持產品族支持產品族
擴展性容易擴展新產品難以擴展新產品族
復雜度相對簡單相對復雜
適用場景單一類型產品相關產品家族

模式選擇指南

在實際開發中,應根據具體需求選擇合適的工廠模式:

  1. 簡單工廠模式:適用于產品類型較少且不經常變化的場景
  2. 工廠方法模式:適用于產品類型可能擴展,但產品族單一的場景
  3. 抽象工廠模式:適用于需要創建多個相關產品族的場景

總結

工廠方法模式及其變體為我們提供了靈活的對象創建機制。通過將對象的創建過程封裝起來,我們實現了創建與使用的分離,提高了代碼的可維護性和擴展性。

  • 簡單工廠:簡單易用,但違反開閉原則
  • 工廠方法:遵循開閉原則,適合單一產品等級結構
  • 抽象工廠:處理產品族,適合相關產品系列的創建

在實際項目中,我們應該根據具體需求選擇合適的模式,避免過度設計。記住,最適合的才是最好的設計。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/98473.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/98473.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/98473.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Ubuntu 24.04 中 nvm 安裝 Node 權限問題解決

個人博客地址:Ubuntu 24.04 中 nvm 安裝 Node 權限問題解決 | 一張假鈔的真實世界 參考nvm的一個issue:https://github.com/nvm-sh/nvm/issues/3363 異常信息如下: $ nvm install 22 Downloading and installing node v22.19.0... Download…

Java面試-線程安全篇

一、synchronized關鍵字: 基本使用與作用:通過搶票代碼示例,展示了synchronized作為對象鎖,可避免多線程超賣或搶到同一張票問題,保證代碼原子性,同一時刻只有一個線程獲得鎖,其他線程阻塞。底層…

R 語言科研繪圖 --- 其他繪圖-匯總2

在發表科研論文的過程中,科研繪圖是必不可少的,一張好看的圖形會是文章很大的加分項。 為了便于使用,本系列文章介紹的所有繪圖都已收錄到了 sciRplot 項目中,獲取方式: R 語言科研繪圖模板 --- sciRplothttps://mp.…

【數學建模學習筆記】啟發式算法:粒子群算法

零基礎小白看懂粒子群優化算法(PSO)一、什么是粒子群優化算法?簡單說,粒子群優化算法(PSO)是一種模擬鳥群 / 魚群覓食的智能算法。想象一群鳥在找食物:每只鳥(叫 “粒子”&#xff0…

【Gitlab】Ubuntu 20.04服務器部署Gitlab

寫一個 適用于 Ubuntu 20.04/22.04 的 GitLab 一鍵部署腳本,包括:安裝依賴安裝 GitLab CE配置公網 IP 或域名自動開啟 HTTPS(Let’s Encrypt)配置防火墻下面是完整腳本:#!/bin/bash# # GitLab 一鍵安裝腳本 # # 1. 檢…

Android 15重磅升級:16KB內存頁機制詳解與適配指南

一、背景隨著Android硬件架構的持續演進,新一代設備開始采用16KB內存頁(Page Size)機制,逐步替代傳統的4KB內存頁設計。此項底層變更對應用兼容性產生直接影響,特別是對依賴Native層庫、JNI接口或自定義內存管理模塊的…

Mybatis-8 動態SQL

動態SQL-官方文檔 文檔地址 動態 SQL_MyBatis中文網 為什么需要動態SQL 1、動態SQL是MyBatis的強大特性之一 2、使用JDBC或其它類似的框架,根據不同條件拼接SQL語句非常麻煩,例如拼接時要確保不能忘記添加必要的空格,還要注意去掉列表最后一…

PySpark數據輸入

PySpark數據輸入 1.理解RDD對象 2.掌握PySpark數據輸入的2種方法 RDD對象 PySpark支持多種數據的輸入,在輸入完成后,都會得到一個:RDD類的對象 RDD全稱為:彈性分布式數據集(Resilient Distributed Datasets&#xff09…

【系統架構設計(16)】軟件架構設計二:軟件架構風格:構建系統的設計模式與選擇指南

文章目錄一、核心思想二、數據流風格:以數據流動為核心的處理模式三、調用返回風格:基于程序調用的層次化組織四、獨立構件風格:基于事件驅動的松耦合架構五、虛擬機風格:提供抽象執行環境的架構模式六、倉庫風格:以數…

MySQL速記小冊(1)

1【Q】:Mysql中的數據排序是怎么實現的?【A】:排序過程中如果字段有索引,則利用索引排序。反之使用文件排序。在文件排序中,如果數據量少則在內存中排序,使用單路排序或雙路排序。如果數據量大則利于磁盤文…

20250904 10:45_排查10.1.3.35新QMS系統RMAN備份失敗問題(優化腳本里的環境配置,增加了check_oracle_env 函數)

一、RMAN備份失敗日志如下 [2025-09-04 04:00:01] 備份腳本啟動 [2025-09-04 04:00:01] 開始 RMAN 備份 CDB: ORCLCDB Message file RMAN<lang>.msb not found Verify that ORACLE_HOME is set properly [2025-09-04 04:00:01] RMAN 備份失敗! 二、原備份腳本存檔…

Vue3源碼reactivity響應式篇之EffectScope

概述 EffectScope是Vue3中一個響應式系統的輔助類&#xff0c;用于管理副作用&#xff08;effect&#xff09;的作用域。它可以幫助我們更好地組織和管理多個effect&#xff0c;便于一起停止或暫停以及恢復&#xff0c;避免了全局狀態的污染和管理的復雜性。 每一個vue組件的實…

MySQL 日志全解析:Binlog/Redo/Undo 等 5 類關鍵日志的配置、作用與最佳實踐

1 二進制日志&#xff08;Binlog&#xff09;&#xff1a;配置與核心作用 Binlog 是 MySQL 中跨存儲引擎的核心日志&#xff0c;記錄所有數據修改操作&#xff0c;主要用于主從復制、數據備份恢復與跨庫遷移。 1.1 Binlog 核心操作 開啟 Binlog 若需開啟 Binlog&#xff0c;需在…

springboot 之 HTML與圖片生成 (2)

前言 之前寫了一篇html轉圖片的 文章&#xff0c;使用中文時會出現亂碼情況&#xff0c;后來又從網上找了下信息&#xff0c;這篇主要介紹下另一個轉換庫。 依賴 <!-- 用于將html轉圖片--><dependency><groupId>gui.ava</groupId><artifactId>…

計算機組成原理:計算機的分類

&#x1f4cc;目錄&#x1f5a5;? 計算機組成原理&#xff1a;計算機的分類——從架構到應用的全景梳理一、按處理數據類型分類&#xff1a;從“數字”到“混合”的演進&#xff08;一&#xff09;數字計算機&#xff1a;離散數據的“精準管家”1. 核心原理2. 關鍵優勢3. 典型…

數據結構——單向循環鏈表代碼(補充)

在此前的文章中&#xff08;鏈接如下&#xff09;&#xff0c;只有單向鏈表的代碼&#xff0c;接下來我們來寫單向循環鏈表&#xff0c;并用其實現一個簡單的學生信息鏈表https://blog.csdn.net/2301_80406299/article/details/151157051?spm1011.2415.3001.10575&sharefr…

【Python自動化】 21.2 Pandas 讀取 Excel 時的 dtype 參數完全指南

一、dtype 參數概述 dtype 參數用于指定列的數據類型&#xff0c;在讀取 Excel 時非常重要&#xff0c;可以&#xff1a; 提高內存效率避免自動類型推斷錯誤確保數據一致性提升讀取性能 二、基本用法 1. 基礎語法 import pandas as pd# 指定列數據類型 df pd.read_excel(data.…

gtest全局套件的測試使用

gtest全局套件的測試使用 #include <iostream> #include "gtest/gtest.h" #include <unordered_map>class MyEnvironment: public testing::Environment {public:virtual void SetUp() override{std::cout<<"單元測試前的環境初始化&#xff…

【系統分析師】第7章-基礎知識:軟件工程(核心總結)

更多內容請見: 備考系統分析師-專欄介紹和目錄 文章目錄 一、軟件工程的基本概念 1.1 定義與意義 1.2 軟件工程的基本原則 1.3 核心定義與邊界 1.4 四大核心原則 1.5 三大核心目標 二、軟件生命周期 2.1 定義與階段劃分 2.2 軟件生命周期模型 三、軟件開發方法 3.1 結構化方法…

量化基金從小白到大師 - 金融數據獲取大全:從免費API到Tick級數據實戰指南

量化基金從小白到大師 - 金融數據獲取大全&#xff1a;從免費API到Tick級數據實戰指南 各位&#xff0c;今天咱們要啃一塊硬骨頭——金融數據獲取。別看這話題基礎&#xff0c;它可是整個量化大廈的地基&#xff0c;地基不穩&#xff0c;再牛的策略都得塌房。我見過太多人&…