Python設計模式詳解:策略模式(Strategy Pattern)實戰指南

Python設計模式詳解:策略模式實戰指南

    • 什么是策略模式?
      • 核心組件
    • 基礎實現
    • 利用Python特性的高級實現
    • 使用裝飾器的策略模式
    • 策略模式的優勢
    • 策略模式的適用場景
    • 實際應用案例:電商折扣系統
    • 注意事項
    • 總結

在面向對象編程中,設計模式為常見問題提供了可重用的解決方案。策略模式是行為設計模式中最廣泛使用的一種,它允許在運行時選擇算法。本文將全面介紹如何在Python中理解和實現策略模式。

什么是策略模式?

策略模式定義了一系列算法,將每個算法封裝起來,并使它們可以互換。它允許算法獨立于使用它們的客戶端而變化。

核心組件

  • 上下文(Context):維護一個指向策略對象的引用
  • 策略(Strategy):所有支持算法的公共接口
  • 具體策略(Concrete Strategies):策略接口的具體實現

基礎實現

讓我們從一個簡單的支付系統示例開始:

from abc import ABC, abstractmethod# 策略接口
class PaymentStrategy(ABC):@abstractmethoddef pay(self, amount):pass# 具體策略實現
class CreditCardPayment(PaymentStrategy):def __init__(self, name, card_number, cvv):self.name = nameself.card_number = card_numberself.cvv = cvvdef pay(self, amount):print(f"使用信用卡支付 ${amount},卡號尾號 {self.card_number[-4:]}")class PayPalPayment(PaymentStrategy):def __init__(self, email):self.email = emaildef pay(self, amount):print(f"使用PayPal支付 ${amount},賬戶 {self.email}")class BitcoinPayment(PaymentStrategy):def __init__(self, wallet_address):self.wallet_address = wallet_addressdef pay(self, amount):print(f"使用比特幣支付 ${amount},錢包地址 {self.wallet_address[:8]}...")# 上下文
class ShoppingCart:def __init__(self):self.items = []self.payment_strategy = Nonedef add_item(self, item, price):self.items.append((item, price))def set_payment_strategy(self, strategy):self.payment_strategy = strategydef calculate_total(self):return sum(price for item, price in self.items)def checkout(self):if not self.payment_strategy:raise Exception("未設置支付策略")total = self.calculate_total()self.payment_strategy.pay(total)# 使用示例
cart = ShoppingCart()
cart.add_item("筆記本電腦", 1200)
cart.add_item("鼠標", 25)# 使用信用卡支付
cart.set_payment_strategy(CreditCardPayment("張三", "1234567890123456", "123"))
cart.checkout()# 使用PayPal支付
cart.set_payment_strategy(PayPalPayment("zhangsan@example.com"))
cart.checkout()

利用Python特性的高級實現

Python的動態特性允許更靈活的實現:

from enum import Enum
from typing import Callable# 使用函數作為策略
def bubble_sort(data):print("使用冒泡排序")# 實現細節return sorted(data)def quick_sort(data):print("使用快速排序")# 實現細節return sorted(data)def merge_sort(data):print("使用歸并排序")# 實現細節return sorted(data)# 策略枚舉
class SortStrategy(Enum):BUBBLE = bubble_sortQUICK = quick_sortMERGE = merge_sortclass Sorter:def __init__(self, strategy: SortStrategy):self.strategy = strategydef sort(self, data):return self.strategy.value(data)# 使用示例
data = [64, 34, 25, 12, 22, 11, 90]
sorter = Sorter(SortStrategy.QUICK)
result = sorter.sort(data)

使用裝飾器的策略模式

# 策略注冊裝飾器
strategies = {}def register_strategy(name):def decorator(func):strategies[name] = funcreturn funcreturn decorator@register_strategy("discount_10")
def ten_percent_discount(price):return price * 0.9@register_strategy("discount_20")
def twenty_percent_discount(price):return price * 0.8@register_strategy("holiday_special")
def holiday_discount(price):return price * 0.7 if price > 100 else priceclass PriceCalculator:def __init__(self, strategy_name):self.strategy = strategies.get(strategy_name)if not self.strategy:raise ValueError(f"未知的策略: {strategy_name}")def calculate(self, price):return self.strategy(price)# 使用示例
calculator = PriceCalculator("holiday_special")
final_price = calculator.calculate(150)
print(f"最終價格: ${final_price}")

策略模式的優勢

  1. 算法可以自由切換:可以在運行時動態更換算法
  2. 避免使用多重條件判斷:替代大量的if-else或switch語句
  3. 擴展性良好:可以方便地添加新的算法
  4. 符合開閉原則:對擴展開放,對修改關閉

策略模式的適用場景

  1. 多個類只有算法不同:當系統中存在大量相似的類,只有行為不同時
  2. 需要算法動態切換:需要在運行時選擇不同的算法
  3. 消除復雜的條件分支:替代復雜的if-else或switch語句
  4. 算法需要獨立變化:算法的變化不應影響客戶端

實際應用案例:電商折扣系統

from abc import ABC, abstractmethod
from datetime import datetimeclass DiscountStrategy(ABC):@abstractmethoddef calculate_discount(self, original_price, quantity):passclass NoDiscount(DiscountStrategy):def calculate_discount(self, original_price, quantity):return original_price * quantityclass BulkDiscount(DiscountStrategy):def calculate_discount(self, original_price, quantity):if quantity >= 10:return original_price * quantity * 0.9  # 10%折扣return original_price * quantityclass SeasonalDiscount(DiscountStrategy):def calculate_discount(self, original_price, quantity):# 假設夏季有折扣current_month = datetime.now().monthif 6 <= current_month <= 8:return original_price * quantity * 0.85  # 15%折扣return original_price * quantityclass MemberDiscount(DiscountStrategy):def __init__(self, is_vip=False):self.is_vip = is_vipdef calculate_discount(self, original_price, quantity):if self.is_vip:return original_price * quantity * 0.8  # 20%折扣return original_price * quantity * 0.95    # 5%折扣class Order:def __init__(self, product_name, price, quantity):self.product_name = product_nameself.price = priceself.quantity = quantityself.discount_strategy = NoDiscount()def set_discount_strategy(self, strategy):self.discount_strategy = strategydef get_total(self):return self.discount_strategy.calculate_discount(self.price, self.quantity)# 使用示例
order = Order("商品A", 100, 15)
print(f"原價: ${order.get_total()}")  # 1500# 設置批量折扣
order.set_discount_strategy(BulkDiscount())
print(f"批量折扣后: ${order.get_total()}")  # 1350# 設置會員折扣
order.set_discount_strategy(MemberDiscount(is_vip=True))
print(f"會員折扣后: ${order.get_total()}")  # 1200

注意事項

  1. 策略數量:如果策略很少且不經常變化,可能不需要使用策略模式
  2. 客戶端了解策略:客戶端必須了解不同策略的區別才能選擇合適的策略
  3. 對象數量增加:每種策略都需要創建一個策略類,可能會增加系統中的對象數量

總結

策略模式是一種非常實用的設計模式,特別適合處理算法需要動態切換的場景。通過將算法封裝在獨立的類中,可以實現算法的靈活替換,同時保持代碼的清晰和可維護性。在Python中,我們可以利用其動態特性,使用函數、裝飾器等方式來簡化策略模式的實現。

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

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

相關文章

一次 web 請求響應中,通常那個部分最耗時?

文章目錄一次Web請求的完整旅程1. DNS解析2. TCP連接建立3. 發送HTTP請求4. 服務器處理5. 服務器響應6. 瀏覽器渲染哪個環節通常最耗時&#xff1f;1. 數據庫查詢2. 外部API調用3. 復雜的業務邏輯如何優化各個環節&#xff1f;1. 數據庫優化2. 緩存策略3. 異步處理總結一次Web請…

IO流-概述和體系

1.什么是I0流?存儲和讀取數據的解決方案|: input 0: output流:像水流一樣傳輸數據2.10流的作用?用于讀寫數據(本地文件&#xff0c;網絡)3. I0流按照流向可以分類哪兩種流?輸出流:程序-->文件輸入流:文件-->程序4. I0流按照操作文件的類型可以分類哪兩種流?…

提高建筑舒適度與能源效率,樓宇自控系統意義重大

隨著城市化進程的加速和人們對建筑環境要求的不斷提高&#xff0c;如何在保證建筑舒適度的同時提升能源效率&#xff0c;成為建筑行業面臨的重要課題。樓宇自控系統&#xff08;Building Automation System&#xff0c;簡稱BAS&#xff09;作為現代智能建筑的核心組成部分&…

學習筆記《區塊鏈技術與應用》第4天 比特幣腳本語言

輸入0.7 輸出0.5 23個確認 不太可能回滾了交易id hash值 版本 locktime 交易剩下時間&#xff1a;0立即生效 confirmation:確認信息 time&#xff1a;產生時間 blocktime&#xff1a;塊產生時間vout: 交易中第0個輸入 scriptSig&#xff1a;輸入腳本&#xff08;input script)n…

3.Linux 系統文件類型與文件權限

1.文件類型Linux 下所有的東西都可以看做文件&#xff0c;Linux 將文件分為以下幾種類型&#xff1a;普通文件 ‘-’目錄文件 ‘d’管道文件 ‘p’鏈接文件 ‘l’設備文件&#xff08;塊設備 ’b’ 、字符設備 ‘c’&#xff09;套接字文件 ‘s’Linux 上不以文件的擴展名區別文…

訂單識別技術原理及場景應用

訂單OCR&#xff08;光學字符識別&#xff09;技術通過圖像處理和深度學習算法&#xff0c;將紙質或電子版訂單中的文字信息轉化為結構化數據。以下是其技術原理和典型應用場景的詳細解析&#xff1a;一、技術原理剖析1. 核心處理流程圖像預處理去噪&#xff1a;消除陰影、折痕…

[優選算法]復寫零

題目鏈接 LeetCode復寫零 題目描述 題目解析 一、問題理解 題目要求&#xff1a;給定一個整數數組 arr&#xff0c;在不創建新數組的情況下&#xff0c;將每個出現的 0 復寫一遍&#xff08;即一個 0 變成兩個 0&#xff09;&#xff0c;同時保持其他元素的相對順序不變。復…

element UI的el-table組件,實現可以拖動

表格 <div class"main_table"><el-table id"elTableid" :data"fieldArr" border style"width: 100%" row-class-name"drag-row"current-row-key highlight-current-row><el-table-column type"index&qu…

Android Emoji 全面解析:從使用到自定義

引言 Emoji已經成為現代數字通信不可或缺的一部分&#xff0c;這些小小的圖標能夠跨越語言障礙&#xff0c;直觀地表達情感和想法。在Android開發中&#xff0c;正確處理和顯示Emoji是提升用戶體驗的重要環節。本文將全面介紹Android平臺上的Emoji支持&#xff0c;包括系統集成…

數據中心入門學習(五):服務器CPU

目錄CPU1 概述1.1 概念1.2 馮諾依曼架構1.3 常見參數&#xff08;評估性能&#xff09;1.4 按指令集分類2 CPU發展2.1 發展史2.2 行業產業鏈2.3 英特爾 Xeon 至強處理器2.4 AMD Zen架構補充1 寄存器、存儲器、內存、緩存、硬盤區別與聯系&#xff1f;2 浮點單元參考本篇記錄和梳…

基于MySQL實現基礎圖數據庫

基于MySQL實現基礎圖數據庫 一、概念 圖數據庫是一種用于存儲和查詢具有復雜關系的數據的數據庫。在這種數據庫中&#xff0c;數據被表示為節點&#xff08;實體&#xff09;和邊&#xff08;關系&#xff09;。圖數據庫的核心優勢在于能夠快速地查詢和處理節點之間的關系。 圖…

RAG面試內容整理-9. 查詢改寫與增強(Query Rewriting, Query Expansion)

查詢改寫和查詢增強是兩種提升檢索效果的技術,目標是在不改變用戶意圖的前提下,使檢索器收到的查詢更全面或明確,從而找到更多相關信息。 查詢改寫通常指將原始查詢轉換成語義等價但更明晰的形式。上一節談到的對話查詢改寫是一個典型場景。在一般情況下,查詢改寫也適用于澄…

golang設置http代理

問題場景&#xff1a; golang通過eino的官方agent示例調用duckduckgo進行聯網搜索時出現網絡問題&#xff0c;電腦此時是掛了工具的瀏覽器整出打開 官方示例&#xff1a;https://www.cloudwego.io/zh/docs/eino/quick_start/agent_llm_with_tools/ 問題原因&#xff1a;go代碼沒…

Elasticsearch 現在默認啟用 BBQ,并通過 ACORN 實現過濾向量搜索

作者&#xff1a;來自 Elastic Gilad Gal 探索 Elasticsearch 的向量搜索如何以更快的速度、更低的成本提供更優結果。 試用向量搜索&#xff1a;使用這套自定進度的 Search AI 實操學習課程&#xff0c;親自體驗向量搜索。你可以開始免費云試用&#xff0c;或立即在本地機器上…

Java 14 新特性解析與代碼示例

Java 14 新特性解析與代碼示例 文章目錄Java 14 新特性解析與代碼示例1. 開關表達式&#xff08;Switch Expressions&#xff09;2. 記錄類型&#xff08;Records&#xff09;3. 文本塊&#xff08;Text Blocks&#xff09;4. instanceof的模式匹配&#xff08;Pattern Matchin…

在虛擬機ubuntu上修改framebuffer桌面不能顯示圖像

目錄 一、測試程序 二、排查原因 三、為什么 Xorg 會導致程序無法工作&#xff1f; 一、測試程序 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #in…

語言模型的評估指標整理

語言模型&#xff08;Language Models&#xff09;是自然語言處理&#xff08;NLP&#xff09;的核心組件&#xff0c;廣泛應用于機器翻譯、文本生成、對話系統等領域。隨著模型復雜度的提升&#xff0c;如何科學、系統地評估模型性能變得至關重要。評估指標不僅幫助我們理解模…

【開發技術】.Net中配置Serilog日志分級記錄

目錄 一、目的 二、解決方案 2.1 下載serilog包 2.2 Serilog配置 2.2.1 使用多個File sink配置不同的最小日志級別 2.2.2 使用Filter條件分流到不同文件 三、使用建議 四、文章總結 一、目的 在日常開發中&#xff0c;需要根據不同的場景去記錄日志&#xff0c;根據實際…

聊聊如何判斷發現的缺陷屬于前后端

目錄 一、觀察缺陷現象 二、檢查網絡請求&#xff08;核心方法&#xff09; 三、模擬請求驗證后端 四、查看日志 五、數據流分析 六、判斷前后端缺陷方法 判斷發現的缺陷是前后端&#xff0c;可以通過觀察缺陷現象&#xff0c;檢查網絡請求&#xff0c;查看后端日志&…

Python3與MySQL的PyMySQL連接與應用

Python3與MySQL的PyMySQL連接與應用 引言 隨著互聯網技術的飛速發展,數據庫在各個領域的應用日益廣泛。MySQL作為一種開源的關系型數據庫管理系統,因其穩定性和高效性,被廣泛應用于各種場景。Python作為一種高級編程語言,以其簡潔、易讀、易學等特點,受到了廣大開發者的…