網(wǎng)站首頁 編程語言 正文
策略模式主要解決在有多種算法相似的情況下,使用 if…else 所帶來的復(fù)雜和難以維護(hù),其實際就是用來抽象變化的(和開放-封閉原則是一個原理),只要在分析過程中我們發(fā)現(xiàn)需要在不同的時間運用不同類型的業(yè)務(wù)規(guī)則或者代碼中可能會出現(xiàn)很多變化,就可以考慮使用策略模式來處理這種變化。
策略模式通常的使用方法就是一個抽象策略類,若干具體策略類和一個Context類,同時Conetext類可以結(jié)合簡單工廠模式讓用戶與策略類完全解耦,比如可以向Context類的構(gòu)造函數(shù)中傳入?yún)?shù)而不是策略類,然后在Conext的構(gòu)造函數(shù)里用簡單工廠模式根據(jù)傳遞的參數(shù)初始化策略類,甚至還可以什么都不傳,定義一個默認(rèn)策略供用戶使用(簡單工廠不一定是要一個單獨的類)。Conetext類中包含一個策略類的指針指向簡單工廠實例化出的具體策略類對象,還包含一個contextDeloy接口用于通過策略類指針去調(diào)用實例化出的具體策略類對象的接口,可以讓用戶面對Context的接口編程,而不與策略類接口直接耦合 ,方便策略類日后更改接口,同時還需要一個get接口,用于獲取簡單工廠中實例化出的對象。在業(yè)務(wù)邏輯層,我們先判斷簡單工廠模式實例化的具體對象是否為空,如果不為空,我們就可以通過contextDeloy接口去訪問實例化的具體策略類對象的接口。
其實之前的這篇博客https://blog.csdn.net/weixin_44049823/article/details/128907849中,計算器5.0版本就已經(jīng)使用了策略模式,在這篇博客中,我們共實現(xiàn)了計算器的5個版本,最初使用的是簡單粗暴的if-else-if語句來判斷使用哪一種業(yè)務(wù)(運算),到5.0版本,我們抽象出了一個Operation類(策略類),然后又創(chuàng)建了4個具體類,加法運算、減法運算、乘法運算、除法運算類(4個具體策略類),最后創(chuàng)建了一個工廠類用于根據(jù)不同情況實例化不同運算類的對象,其實這之中的一個抽象策略類和4個具體策略類已經(jīng)有策略模式的影子了,但是缺少了其精華Context類。
接下來我將用策略模式改寫之前的計算器5.0版本。
#include<iostream>
using namespace std;
#include<string>
//業(yè)務(wù)邏輯
//異常類用于處理異常情況
class opeException
{
public:
void getMessage()
{
cout << "您的輸入有誤!" << endl;
}
};
//運算類
class Operation
{
//判斷一個字符串是不是數(shù)字
bool isStringNum(string& s)
{
bool flag = true;
for (auto e : s)
if (!(isdigit(e)))
{
flag = false;
break;
}
return flag;
}
protected:
bool isError(string& _strNum1, string& _strNum2, string& _ope)
{
if (!(Operation::isStringNum(_strNum1) && Operation::isStringNum(_strNum2) && (_ope == "+" || _ope == "-" || _ope == "*" || _ope == "/")))
{
return false;
}
}
public:
virtual int getResult()
{
return 0;
}
};
//加法運算類
class addOperation :public Operation
{
private:
string strNum1;
string strNum2;
string ope;
int re;
public:
addOperation(string& _strNum1, string& _strNum2, string& _ope) :strNum1(_strNum1), strNum2(_strNum2), ope(_ope), re(0) {}
virtual int getResult() override
{
if (!isError(strNum1, strNum2, ope))
throw opeException();
else
re = stoi(strNum1) + stoi(strNum2);
return re;
}
};
//減法運算類
class subOperation :public Operation
{
private:
string strNum1;
string strNum2;
string ope;
int re;
public:
subOperation(string& _strNum1, string& _strNum2, string& _ope) :strNum1(_strNum1), strNum2(_strNum2), ope(_ope), re(0) {}
virtual int getResult() override
{
if (!isError(strNum1, strNum2, ope))
throw opeException();
else
re = stoi(strNum1) - stoi(strNum2);
return re;
}
};
//乘法運算類
class mulOperation :public Operation
{
private:
string strNum1;
string strNum2;
string ope;
int re;
public:
mulOperation(string& _strNum1, string& _strNum2, string& _ope) :strNum1(_strNum1), strNum2(_strNum2), ope(_ope), re(0) {}
virtual int getResult() override
{
if (!isError(strNum1, strNum2, ope))
throw opeException();
else
re = stoi(strNum1) * stoi(strNum2);
return re;
}
};
//除法運算類
class divOperation :public Operation
{
private:
string strNum1;
string strNum2;
string ope;
int re;
public:
divOperation(string& _strNum1, string& _strNum2, string& _ope) :strNum1(_strNum1), strNum2(_strNum2), ope(_ope), re(0) {}
virtual int getResult() override
{
if (!isError(strNum1, strNum2, ope))
throw opeException();
else if (stoi(strNum2) != 0)
re = stoi(strNum1) / stoi(strNum2);
else
throw opeException();
return re;
}
};
//Conetext結(jié)合簡單工廠模式
class Context
{
Operation *operation;
public:
Context(string& _strNum1, string& _strNum2, string& _ope)
{
if (_ope == "+")
{
operation = new addOperation(_strNum1, _strNum2, _ope);
}
else if (_ope == "-")
operation = new subOperation(_strNum1, _strNum2, _ope);
else if (_ope == "*")
operation = new mulOperation(_strNum1, _strNum2, _ope);
else if (_ope == "/")
{
operation = new divOperation(_strNum1, _strNum2, _ope);
}
else
operation = nullptr;
}
Operation* get()
{
return operation;
}
int contextResult()
{
return operation->getResult();
}
};
//界面邏輯
int main()
{
try
{
string _strNum1 = " ";
string _strNum2 = " ";
string _ope = " ";
cout << "請輸入左操作數(shù):" << endl;
cin >> _strNum1;
cout << "請輸入右操作數(shù):" << endl;
cin >> _strNum2;
cout << "請輸入操作符:" << endl;
cin >> _ope;
Context context(_strNum1, _strNum2, _ope);
if (context.get() != nullptr)
cout << context.contextResult() << endl;
else
cout << "您的輸入有誤!" << endl;
}
catch (opeException ex)
{
cout << "您的輸入有誤" << endl;
}
return 0;
}
結(jié)合上一篇博客的5.0版本代碼可知,簡單工廠模式需要讓客戶端認(rèn)識兩個類,而策略類只需要讓客戶端認(rèn)識一個類即可,耦合更低。
總結(jié)策略模式的優(yōu)缺點:
優(yōu)點:
1、算法可以自由切換。
2、避免使用多重條件判斷。
3、擴展性良好。
缺點:
1、策略類會增多。
2、所有策略類都需要對外暴露。
注意事項:如果一個系統(tǒng)的策略多于四個,就需要考慮使用混合模式,解決策略類膨脹的問題。
原文鏈接:https://blog.csdn.net/weixin_44049823/article/details/129043252
- 上一篇:沒有了
- 下一篇:沒有了
相關(guān)推薦
- 2022-04-09 python的函數(shù)參數(shù)你了解嗎_python
- 2022-08-16 PostgreSQL怎么創(chuàng)建分區(qū)表詳解_PostgreSQL
- 2022-10-25 記一次生產(chǎn)環(huán)境死鎖問題分析
- 2022-09-22 element form表單循環(huán)校驗(動態(tài)綁定的數(shù)據(jù))
- 2022-02-18 微信小程序----------父組件調(diào)用子組件的方法
- 2023-07-26 TypeScript的類型推導(dǎo)
- 2022-07-15 C#使用BitConverter與BitArray類進(jìn)行預(yù)定義基礎(chǔ)類型轉(zhuǎn)換_C#教程
- 2022-04-01 k8s使用docker作為運行時卡死解決辦法
- 欄目分類
-
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支