[設計模式]行為型模式-策略模式

来源:https://www.cnblogs.com/XY-Heruo/p/18019973
-Advertisement-
Play Games

前言 策略模式定義了一系列演算法,並將每個演算法封裝起來,使它們可以互相替換,且演算法的變換不會影響使用演算法的客戶。 在項目開發中,我們經常要根據不同的場景,採取不同的措施,也就是不同的策略。假設我們需要對a、b這兩個整數進行計算,根據條件的不同,需要執行不同的計算方式。我們可以把所有的操作都封裝在同一個 ...


前言

策略模式定義了一系列演算法,並將每個演算法封裝起來,使它們可以互相替換,且演算法的變換不會影響使用演算法的客戶。

在項目開發中,我們經常要根據不同的場景,採取不同的措施,也就是不同的策略。假設我們需要對a、b這兩個整數進行計算,根據條件的不同,需要執行不同的計算方式。我們可以把所有的操作都封裝在同一個函數中,然後根據if ... else ...的形式來調用不同的計算方式,這種方式稱為硬編碼。

在實際應用中,隨著功能和體驗的不斷增長,我們需要經常添加/修改策略,進而需要不斷修改已有代碼,這不僅會讓這個函數越來越難以維護,還會因為修改帶來一些Bug。因此,為瞭解耦,我們需要使用策略模式,定義一些獨立的類來封裝不同的演算法,每一個類封裝一個具體的演算法。

示例代碼

策略模式的重點在於策略的設定,以及普通類Operator和策略CalStrategy的對接。通過更換實現同一介面的不同策略類。降低了Operator的維護成本,解耦演算法實現。

Go

strategy.go

package strategy  
  
// CalStrategy 是一個策略類  
type CalStrategy interface {  
    do(int, int) int  
}  
  
// Add 為加法策略  
type Add struct{}  
  
func (*Add) do(a, b int) int {  
    return a + b  
}  
  
// Reduce 為減法策略  
type Reduce struct{}  
  
func (*Reduce) do(a, b int) int {  
    return a - b  
}  
  
// Operator 是具體的策略執行者  
type Operator struct {  
    strategy CalStrategy  
}  
  
// 設置策略  
func (o *Operator) setStrategy(strategy CalStrategy) {  
    o.strategy = strategy  
}  
  
// 調用策略中的方法  
func (o *Operator) calc(a, b int) int {  
    return o.strategy.do(a, b)  
}

單元測試

package strategy  
  
import "testing"  
  
func TestStrategy(t *testing.T) {  
    operator := Operator{}  
    operator.setStrategy(&Add{})  
    if operator.calc(1, 2) != 3 {  
       t.Fatal("Add strategy error")  
    }  
  
    operator.setStrategy(&Reduce{})  
    if operator.calc(2, 1) != 1 {  
       t.Fatal("Reduce strategy error")  
    }  
}

Python

from abc import ABC, abstractmethod


class CalStrategy(ABC):
    """策略類
    """
    @abstractmethod
    def do(self, a: int, b: int) -> int:
        pass


class Add(CalStrategy):
    """加法策略
    """
    def do(self, a: int, b: int) -> int:
        return a + b


class Reduce(CalStrategy):
    """減法策略
    """
    def do(self, a: int, b: int) -> int:
        return a - b


class Operator:
    """策略執行者
    """
    def __init__(self):
        self.strategy = None

    def set_strategy(self, strategy: CalStrategy):
        """設置策略
        """
        self.strategy = strategy

    def calc(self, a: int, b: int) -> int:
        """調用策略中的方法
        """
        return self.strategy.do(a, b)


if __name__ == "__main__":
    operator = Operator()
    operator.set_strategy(Add())
    print(operator.calc(1, 2))

    operator.set_strategy(Reduce())
    print(operator.calc(4, 3))

參考

  • 孔令飛 - 企業級Go項目開發實戰

本文來自博客園,作者:花酒鋤作田,轉載請註明原文鏈接:https://www.cnblogs.com/XY-Heruo/p/18019973


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

-Advertisement-
Play Games
更多相關文章
  • Howdz Dashboard —— 一個基於 Vue3、Typescript、Vite 的完全自定義配置的瀏覽器起始頁,支持 Chrome 插件和 Edge 插件。 ...
  • 隨著 JavaScript 開發變得越來越廣泛,命名空間和依賴關係變得越來越難以處理。人們已經開發出不同的解決方案以模塊系統的形式來解決這個問題。 CommonJS(CJS) CommonJS 是一種同步載入模塊的規範,主要用於伺服器端的 Node.js 環境。 // 模塊導出 module.exp ...
  • 為什麼在js中需要添加addEventListener()? 1.What? addEventListener(監聽器) EventTarget.addEventListener()方法將指定的監聽器註冊到 EventTarget 上,當該對象觸髮指定的事件時,指定的回調函數就會被執行。事件目標可以 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 前言 在日常的開發中,我們經常能碰見服務端需要主動推送給客戶端數據的業務場景,比如數據大屏的實時數據,比如消息中心的未讀消息,比如聊天功能等等。 本文主要介紹SSE的使用場景和如何使用SSE。 服務端向客戶端推送數據的實現方案有哪幾種? ...
  • 這篇筆記總結自網課DNS解析和優化【渡一教育】 DNS用於將功能變數名稱轉換成IP地址。 特點: DNS解析過程耗費時間長; DNS有本地緩存。 DNS解析完成得到IP地址,這個IP地址會存儲到本地設備,後續再讀這個功能變數名稱會直接返回本地緩存的IP地址。 用戶瀏覽網頁中的DNS解析流程 首先用戶輸入url地 ...
  • 在 Vue 中說到v-bind大多數時候都是想到template中動態綁定script中的響應式數據。但其實在單文件組件(SFC)中, ...
  • Vite腳手架在打包代碼的時候,會把源代碼里對於靜態資源的訪問路徑轉換為打包後靜態資源文件的路徑。動態訪問靜態資源通常導致讀取不到文件,因為源代碼中使用的路徑是src中的,而打包之後靜態資源帶上了文件指紋,代碼中的路徑卻沒有隨之改變。 ...
  • 前言 單例模式是最簡單的一種模式。在Go中,單例模式指的是全局只有一個實例,並且它負責創建自己的對象。單例模式有減少記憶體和系統資源開銷、防止多個實例產生衝突等優點。 因為單例模式保證了實例的全局唯一性,並且只被初始化一次,所以比較適合全局共用一個實例,且只需要被初始化一次的場景,例如資料庫實例、全局 ...
一周排行
    -Advertisement-
    Play Games
  • GoF之工廠模式 @目錄GoF之工廠模式每博一文案1. 簡單說明“23種設計模式”1.2 介紹工廠模式的三種形態1.3 簡單工廠模式(靜態工廠模式)1.3.1 簡單工廠模式的優缺點:1.4 工廠方法模式1.4.1 工廠方法模式的優缺點:1.5 抽象工廠模式1.6 抽象工廠模式的優缺點:2. 總結:3 ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 本章將和大家分享ES的數據同步方案和ES集群相關知識。廢話不多說,下麵我們直接進入主題。 一、ES數據同步 1、數據同步問題 Elasticsearch中的酒店數據來自於mysql資料庫,因此mysql數據發生改變時,Elasticsearch也必須跟著改變,這個就是Elasticsearch與my ...
  • 引言 在我們之前的文章中介紹過使用Bogus生成模擬測試數據,今天來講解一下功能更加強大自動生成測試數據的工具的庫"AutoFixture"。 什麼是AutoFixture? AutoFixture 是一個針對 .NET 的開源庫,旨在最大程度地減少單元測試中的“安排(Arrange)”階段,以提高 ...
  • 經過前面幾個部分學習,相信學過的同學已經能夠掌握 .NET Emit 這種中間語言,並能使得它來編寫一些應用,以提高程式的性能。隨著 IL 指令篇的結束,本系列也已經接近尾聲,在這接近結束的最後,會提供幾個可供直接使用的示例,以供大伙分析或使用在項目中。 ...
  • 當從不同來源導入Excel數據時,可能存在重覆的記錄。為了確保數據的準確性,通常需要刪除這些重覆的行。手動查找並刪除可能會非常耗費時間,而通過編程腳本則可以實現在短時間內處理大量數據。本文將提供一個使用C# 快速查找並刪除Excel重覆項的免費解決方案。 以下是實現步驟: 1. 首先安裝免費.NET ...
  • C++ 異常處理 C++ 異常處理機制允許程式在運行時處理錯誤或意外情況。它提供了捕獲和處理錯誤的一種結構化方式,使程式更加健壯和可靠。 異常處理的基本概念: 異常: 程式在運行時發生的錯誤或意外情況。 拋出異常: 使用 throw 關鍵字將異常傳遞給調用堆棧。 捕獲異常: 使用 try-catch ...
  • 優秀且經驗豐富的Java開發人員的特征之一是對API的廣泛瞭解,包括JDK和第三方庫。 我花了很多時間來學習API,尤其是在閱讀了Effective Java 3rd Edition之後 ,Joshua Bloch建議在Java 3rd Edition中使用現有的API進行開發,而不是為常見的東西編 ...
  • 框架 · 使用laravel框架,原因:tp的框架路由和orm沒有laravel好用 · 使用強制路由,方便介面多時,分多版本,分文件夾等操作 介面 · 介面開發註意欄位類型,欄位是int,查詢成功失敗都要返回int(對接java等強類型語言方便) · 查詢介面用GET、其他用POST 代碼 · 所 ...
  • 正文 下午找企業的人去鎮上做貸後。 車上聽同事跟那個司機對罵,火星子都快出來了。司機跟那同事更熟一些,連我在內一共就三個人,同事那一手指桑罵槐給我都聽愣了。司機也是老社會人了,馬上聽出來了,為那個無辜的企業經辦人辯護,實際上是為自己辯護。 “這個事情你不能怪企業。”“但他們總不能讓銀行的人全權負責, ...