假設我們要做乙個外賣平台,有這樣的需求:
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...