使用策略模式和工廠方法改進if else的實現

2021-10-25 10:42:32 字數 3385 閱讀 1901

假設我們要做乙個外賣平台,有這樣的需求:

1、外賣平台上的某家店鋪為了**,設定了多種會員優惠,其中包含超級會員折扣8折、普通會員折扣9折和普通使用者沒有折扣三種。

2、希望使用者在付款的時候,根據使用者的會員等級,就可以知道使用者符合哪種折扣策略,進而進行打折,計算出應付金額。

3、隨著業務發展,新的需求要求專屬會員要在店鋪下單金額大於30元的時候才可以享受優惠。

4、接著,又有乙個**的需求,如果使用者的超級會員已經到期了,並且到期時間在一周內,那麼就對使用者的單筆訂單按照超級會員進行折扣,並在收銀台進行強提醒,引導使用者再次開通會員,而且折扣只進行一次。

那麼,我們可以看到以下偽**:

double

calprice

(double orderprice, string buyertype)}if

(使用者是超級會員)

if(使用者是普通會員)

return

9折**;

}return 原價;

}

以上,就是對於這個需求的一段**計算邏輯,使用偽**都這麼複雜,如果是真的寫**,那複雜度可想而知。

這樣的**中,有很多if-else,並且還有很多的if-else的巢狀,無論是可讀性還是可維護性都非常低。

那麼,如何改善呢?

首先定義乙個藉口:

class

userpayservice

virtual

double

quote

(double orderprice)=0

;};

接著定義幾個策略類:

class

particularlyvipservice

:public userpayservice}}

;class

supervippayservice

:public userpayservice};

class

vippayservice

:public userpayservice

return

0.9*orderprice;

}bool hastempcostright;}

;

在引入了策略之後,我們可以按照如下方式進行計算:

#include

"strategy_factory.h"

#include

intmain()

由此我們就是使用策略模式根據new出的不同會員的策略類進行不同的計算**方法。

但是在真實的專案中,我們需要先得到使用者的會員等級,比如從資料庫中查出會員的等級,然後根據等級獲取不同的策略類執行計算**方法。那麼真真正的計算**的方法偽**應該是:

double

calprice

(double orderprice,user user)

if(viptype == 超級會員)

if(viptype == 普通會員)

return 原價;

}

我們知道策略模式的乙個缺點:客戶端必須知道所有的策略類,並自行決定使用哪乙個策略類。這就意味著客戶端必須理解這些演算法的區別,以便適時選擇恰當的演算法類。

也就是說,雖然在計算**的時候沒有if-else了,但是選擇具體的策略的時候還是不可避免的還是要有一些if-else。

為了改進這一點,我們可以定義並暴露統一穩定的介面,將內部可能變化的實現隔離,面向介面而非實現,這樣客戶端不需對所有策略有過多的了解,只要提供介面的入參即可得到相應的策略。(客戶端只要提供使用者型別標識,即可得到相應的策略)

對於會員的策略物件我們可以使用工廠模式獲取:

建立乙個工廠類:

class

userpayservicestrategyfactory

static

void

reg(std::string usertype, userpayservice* userpayservice)};

std::unordered_map> userpayservicestrategyfactory::services;

此時我們可以由會員型別直接由工廠得到會員物件(指標),並以此(策略方法)計算得到應付**:

//註冊物件指標表

userpayservicestrategyfactory userpayservice;

userpayservice* supervippay =

newsupervippayservice()

; userpayservice.

reg(

"supervip"

, supervippay)

; userpayservice* vippay =

newvippayservice()

; userpayservice.

reg(

"vip"

, vippay)

; userpayservice* particularlyvippay =

newparticularlyvipservice()

; userpayservice.

reg(

"particularlyvip"

, particularlyvippay)

;double quoteinst1 = userpayservice.

getbyusertype

("particularlyvip")-

>

quote

(300);

std::cout <<

"particularlyvipservice quote = "

<< quoteinst1 << std::endl;

double quoteinst2 = userpayservice.

getbyusertype

("supervip")-

>

quote

(300);

std::cout <<

"supervippayservice quote = "

<< quoteinst2 << std::endl;

double quoteinst3 = userpayservice.

getbyusertype

("vip")-

>

quote

(300);

std::cout <<

"vippayservice quote = "

<< quoteinst3 << std::endl;

此時我們已經可以僅給出會員型別及消費金額即得到相應的物件,並且直接呼叫統一的介面即可計算應付金額。

簡單工廠模式 策略模式與工廠方法模式

用三種設計模式實現同一種功能 四則運算。三種設計模式相同的部分為四則運算類的設計,包括基類,加法運算類,減法運算類,乘法運算類和除法運算類,其 如下 class cclac class cclacadd public cclac class cclacsub public cclac class c...

工廠方法模式 工廠方法模式

工廠方法模式是簡單工廠模式的公升級版,簡單工廠模式不符合設計模式的原則 即 單一職責,開閉原則 優點 職責明確,擴充套件方便 缺點 需要建立多個工廠 實現步驟 1.將工廠通用方法抽取介面 例如 ifactory 2.將產品抽取介面 例如 icar 3.實現各種產品 例如 baomacar,benti...

工廠模式 和工廠方法

簡單的工廠模式 實現計算器 1 採用運算元的方式實現 2 採用工廠 類的方式來建立需要的類,採用比如說switchcase的方式 工廠方法 1 每個需要構建的類都繼承自基類,每個類都有自己的工廠 2 每個類需要建立的時候,就建立自己的工廠,然後,在工廠中呼叫建立自己的行數 工廠方法的好處,不用再sw...