靈活多變的對象創建——工廠方法模式(Python實現)

1. 引言

大家好,又見面了!在上一篇文章中,我們聊了聊簡單工廠模式,今天,我們要進一步探討一種更加靈活的工廠設計模式——工廠方法模式。如果說簡單工廠模式是“萬能鑰匙”,那工廠方法模式就是“變形金剛”。它通過定義一個創建對象的接口,讓子類決定實例化哪一個類,從而應對各種變化。今天,我們就來揭開工廠方法模式的神秘面紗,讓你的Python代碼更加靈活多變。準備好了嗎?Let’s go!

2. 什么是工廠方法模式

工廠方法模式(Factory Method Pattern)是一種創建型設計模式,它定義了一個創建對象的接口,但由子類決定要實例化的類是哪一個。工廠方法模式使一個類的實例化延遲到其子類,簡而言之,就是父類提供一個接口,子類來決定實例化哪個具體的類。

3. 工廠方法模式的實現(Python)

示例一:形狀工廠

假如你是個藝術家,需要畫各種形狀,圓形、方形啥的,你可以用工廠方法模式讓子類決定創建哪些形狀對象:

代碼實現
from abc import ABC, abstractmethod# 定義Shape接口
class Shape(ABC):@abstractmethoddef draw(self):pass# 實現Circle類
class Circle(Shape):def draw(self):print("Drawing a Circle")# 實現Square類
class Square(Shape):def draw(self):print("Drawing a Square")# 定義ShapeFactory接口
class ShapeFactory(ABC):@abstractmethoddef create_shape(self):pass# 實現CircleFactory類
class CircleFactory(ShapeFactory):def create_shape(self):return Circle()# 實現SquareFactory類
class SquareFactory(ShapeFactory):def create_shape(self):return Square()# 使用示例
if __name__ == "__main__":circle_factory = CircleFactory()shape1 = circle_factory.create_shape()shape1.draw()  # 輸出: Drawing a Circlesquare_factory = SquareFactory()shape2 = square_factory.create_shape()shape2.draw()  # 輸出: Drawing a Square
詳細代碼解析
  • Shape是一個抽象基類,定義了draw抽象方法;
  • CircleSquare類實現了Shape接口,具體畫啥樣子它們說了算;
  • ShapeFactory是一個抽象基類,定義了create_shape抽象方法;
  • CircleFactorySquareFactory類實現了ShapeFactory接口,分別負責創建CircleSquare對象;
  • 我們只需通過調用具體的工廠類(如CircleFactorySquareFactory)來創建形狀對象,然后調用相應的draw方法。
示例二:日志記錄器工廠

現在你是個開發者,搞個日志系統,你想要不同級別的日志記錄器來幫你分門別類記錄信息,工廠方法模式也能派上用場:

碼實現
from abc import ABC, abstractmethod# 定義Logger接口
class Logger(ABC):@abstractmethoddef log(self, message):pass# 實現InfoLogger類
class InfoLogger(Logger):def log(self, message):print(f"INFO: {message}")# 實現ErrorLogger類
class ErrorLogger(Logger):def log(self, message):print(f"ERROR: {message}")# 定義LoggerFactory接口
class LoggerFactory(ABC):@abstractmethoddef create_logger(self):pass# 實現InfoLoggerFactory類
class InfoLoggerFactory(LoggerFactory):def create_logger(self):return InfoLogger()# 實現ErrorLoggerFactory類
class ErrorLoggerFactory(LoggerFactory):def create_logger(self):return ErrorLogger()# 使用示例
if __name__ == "__main__":info_logger_factory = InfoLoggerFactory()info_logger = info_logger_factory.create_logger()info_logger.log("This is an informational message.")  # 輸出: INFO: This is an informational message.error_logger_factory = ErrorLoggerFactory()error_logger = error_logger_factory.create_logger()error_logger.log("This is an error message.")  # 輸出: ERROR: This is an error message.
詳細代碼解析
  • Logger是一個抽象基類,定義了log抽象方法;
  • InfoLoggerErrorLogger類實現了Logger接口,分別負責記錄不同級別的日志;
  • LoggerFactory是一個抽象基類,定義了create_logger抽象方法;
  • InfoLoggerFactoryErrorLoggerFactory類實現了LoggerFactory接口,分別負責創建InfoLoggerErrorLogger對象;
  • 你只需通過調用具體的工廠類(如InfoLoggerFactoryErrorLoggerFactory)來創建日志記錄器對象,然后調用相應的log方法。
示例三:數據庫連接工廠

假如你現在是個DBA,需要管理多個數據庫連接,工廠方法模式同樣能幫你搞定這個問題:

代碼實現
from abc import ABC, abstractmethod# 定義DatabaseConnection接口
class DatabaseConnection(ABC):@abstractmethoddef connect(self):pass# 實現MySQLConnection類
class MySQLConnection(DatabaseConnection):def connect(self):print("Connecting to MySQL database...")# 實現PostgreSQLConnection類
class PostgreSQLConnection(DatabaseConnection):def connect(self):print("Connecting to PostgreSQL database...")# 定義DatabaseConnectionFactory接口
class DatabaseConnectionFactory(ABC):@abstractmethoddef create_connection(self):pass# 實現MySQLConnectionFactory類
class MySQLConnectionFactory(DatabaseConnectionFactory):def create_connection(self):return MySQLConnection()# 實現PostgreSQLConnectionFactory類
class PostgreSQLConnectionFactory(DatabaseConnectionFactory):def create_connection(self):return PostgreSQLConnection()# 使用示例
if __name__ == "__main__":mysql_factory = MySQLConnectionFactory()mysql_connection = mysql_factory.create_connection()mysql_connection.connect()  # 輸出: Connecting to MySQL database...postgresql_factory = PostgreSQLConnectionFactory()postgresql_connection = postgresql_factory.create_connection()postgresql_connection.connect()  # 輸出: Connecting to PostgreSQL database...
詳細代碼解析
  • DatabaseConnection是一個抽象基類,定義了connect抽象方法;
  • MySQLConnectionPostgreSQLConnection類實現了DatabaseConnection接口,分別負責不同數據庫的連接;
  • DatabaseConnectionFactory是一個抽象基類,定義了create_connection抽象方法;
  • MySQLConnectionFactoryPostgreSQLConnectionFactory類實現了DatabaseConnectionFactory接口,分別負責創建MySQLConnectionPostgreSQLConnection對象;
  • 你只需通過調用具體的工廠類(如MySQLConnectionFactoryPostgreSQLConnectionFactory)來創建數據庫連接對象,然后調用相應的connect方法。

4. 工廠方法模式的優缺點

優點
  • 解耦:將對象的創建過程與使用過程分離,降低了代碼的耦合度;
  • 靈活性:通過子類來決定具體實例化哪個類,增加了代碼的靈活性;
  • 擴展性:增加新的產品類時,只需添加相應的工廠類即可,不需要修改現有代碼。
缺點
  • 類的數量增加:每增加一個產品類,都需要增加一個相應的工廠類,導致類的數量增多;
  • 代碼復雜度提高:增加了系統的復雜性,理解起來可能會有些困難。

5. 圖示

類圖
../_images/FactoryMethod.jpg
示意圖

img

6. 總結

工廠方法模式是一個非常有用的設計模式,通過定義一個創建對象的接口,讓子類來決定實例化哪一個類,增加了代碼的靈活性和可擴展性。雖然它會增加類的數量和代碼的復雜度,但在大多數情況下,工廠方法模式依然是一個非常實用的解決方案。希望今天的分享能讓大家對工廠方法模式有更深入的理解,如果你在項目中也用到了工廠方法模式,歡迎留言分享你的經驗和見解!
在這里插入圖片描述

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

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

相關文章

生成式人工智能:助攻開發者還是取代開發者?

引言 近年來,生成式人工智能(AIGC)在軟件開發領域掀起了一場革命,為開發者帶來了全新的工具和可能性。從代碼生成、錯誤檢測到自動化測試,AI正在以各種方式改變著開發者的工作方式。然而,這也引發了人們對開…

Python采集京東標題,店鋪,銷量,價格,SKU,評論,圖片

京東的許多數據是通過 JavaScript 動態加載的,包括銷量、價格、評論和評論時間等信息。我們無法僅通過傳統的靜態網頁爬取方法獲取到這些數據。需要使用到如 Selenium 或 Pyppeteer 等能夠模擬瀏覽器行為的工具。 另外,京東的評論系統是獨立的一個系統&a…

offer題目33:判斷是否是二叉搜索樹的后序遍歷序列

題目描述:輸入一個整數數組,判斷該數組是不是某二叉搜索樹的后序遍歷結果。如果是則返回true,否則返回false。假設輸入的數組的任意兩個數字都互不相同。例如,輸入數組{5,7,6,9,11,10,8},則返回true,,因為這個整數是下圖二叉搜索樹…

c++內存管理(上)

目錄 引入 分析 說明 C語言中動態內存管理方式 C內存管理方式 new/delete操作內置類型 new和delete操作自定義類型 引入 我們先來看下面的一段代碼和相關問題 int globalVar 1; static int staticGlobalVar 1; void Test() { static int staticVar 1; int localVar 1…

集訓day3:并查集

一、目錄 1.并查集模版 2.并查集的理解和應用 二、正文 1.并查集模版 P3367 【模板】并查集 - 洛谷 | 計算機科學教育新生態 (luogu.com.cn) 2.并查集的理解與應用 (1).并查集與聯通塊數量 P1197 [JSOI2008] 星球大戰 - 洛谷 | 計算機科學教育新生態 (luogu.com.cn) P1656 炸…

數圖助推朝陽佳惠遼寧華聯開啟數字化導航、精細化管理新紀元!

近期,遼寧省著名零售企業朝陽佳惠與遼寧華聯,秉持創新精神,大膽嘗試,在品類空間管理方面推出了創新舉措。引入了先進的數圖可視化陳列管理系統,通過智能化、直觀化的方式優化商品布局。此舉不僅大幅提高了商品管理的效…

去除各種軟件彈窗教程

清羽彈窗 在mutil/OnlineDialog/onPostExecute前 添加return-void Arm彈窗 第一步,提取安裝包 第二步,搜索代碼Ljava/io/DataOutputStream;->flush()V 第三步,往上看找到 .registers 10 在下面加return-void 云注入彈窗 第一種方法:dex搜…

Sql 導入到 Excel 工具

Sql 導入到 Excel 工具 這個VBA宏的步驟如下: 通過文件對話框選擇SQL文件。讀取文件內容。解析文件中的每一行,如果包含“insert into”,則提取表名。檢查是否已經存在以表名命名的工作表,如果不存在則創建新的工作表。將數據插…

element-ui封裝分頁組件:實現首頁、上一頁、下一頁、末頁、跳轉按鈕

首頁、上一頁、下一頁、末頁、跳轉按鈕 因為el-pagination只有一個插槽,所以通過兩個el-pagination插槽分別加入首頁、末頁按鈕,再拼接這兩個el-pagination的方式來實現首頁、末頁按鈕跳轉按鈕不用加事件,如果el-pagination修改了前往的頁數…

【work】AI八股-神經網絡相關

Deep-Learning-Interview-Book/docs/深度學習.md at master amusi/Deep-Learning-Interview-Book GitHub 網上相關總結: 小菜雞寫一寫基礎深度學習的問題(復制大佬的,自己復習用) - 知乎 (zhihu.com) CV面試問題準備持續更新貼 …

VOI(Virtual Operating System Infrastructure,虛擬操作系統基礎架構)

VOI(Virtual Operating System Infrastructure,虛擬操作系統基礎架構)架構在桌面虛擬化領域具有其獨特的優勢,使得它在某些場景下表現尤為出色。以下是幾個具體場景: 1. 重載性能需求場景 表現: 高效利用…

聚類分析方法(二)

目錄 三、層次聚類方法(一)層次聚類策略(二)AGNES算法(三)DIANA算法 四、密度聚類方法(一)基本概念(二)算法描述(三)計算實例&#xf…

Google賬號輸入用戶名和密碼后提醒要到手機通知點是,還要點擊數字,但是我手機收不到

有一些朋友換了一個新的電腦后手機登錄谷歌賬號時,用戶名和密碼都正確輸入以后,第三步彈出一個提示,要在手機上的通知欄點擊是,并且點擊手機上相應的數字才能繼續登錄。 但是自己的手機上下拉通知欄卻沒有來自谷歌的通知&#xf…

ADOQuery 查詢MSSQL存儲過程一個莫名其妙的錯誤;

在 SSMS 中執行完成正常的的存儲過程。 也能正常的返回想要的數據,,然后通過 ADO 查詢時,總是提法 某 字段不存在的問題; 此問題困擾了一天。 例如(當然,實際數據結構比下面舉例的復雜)&…

C++八股(二)之C++11新特性

一、C++11有什么新特性?? 自動類型推導(Type Inference):引入了 auto 關鍵字,允許編譯器根據初始化表達式的類型自動推導變量的類型。統一的初始化語法(Uniform Initialization Syntax):引入了用花括號 {} 進行初始化的統一語法,可以用于初始化各種類型的對象,包括基…

符號同步、定時同步和載波同步

符號同步、定時同步和載波同步是通信系統中重要的同步技術,它們各自承擔著不同的功能和作用。以下是對這三種同步技術的詳細解釋: 符號同步 定義: 符號同步,也稱為定時恢復或時鐘恢復,是指在數字通信系統中&#xff…

繼承關系中的訪問控制

繼承關系中的訪問控制 類中成員的訪問權限類繼承中的訪問權限派生類向基類轉換的權限問題(向上轉型)友元在繼承中的訪問權限 類中成員的訪問權限 public:類的對象(外部)可以訪問,派生類也可以訪問protecte…

LeNet原理及代碼實現

目錄 1.原理及介紹 2.代碼實現 2.1model.py 2.2model_train.py 2.3model.test.py 1.原理及介紹 2.代碼實現 2.1model.py import torch from torch import nn from torchsummary import summaryclass LeNet(nn.Module):def __init__(self):super(LeNet, self).__init__…

nuxt、vue樹形圖d3.js

直接上代碼 //安裝 npm i d3 --save<template><div class"d3"><div :id"id" class"d3-content"></div></div> </template> <script> import * as d3 from "d3";export default {props: {d…

Github Actions 構建Vue3 + Vite項目

本篇文章以自己創建的項目為例&#xff0c;用Github Actions構建。 Github地址&#xff1a;https://github.com/ling08140814/myCarousel 訪問地址&#xff1a;https://ling08140814.github.io/myCarousel/ 具體步驟&#xff1a; 1、創建一個Vue3的項目&#xff0c;并完成代…