網站首頁 編程語言 正文
策略模式主要解決在有多種算法相似的情況下,使用 if…else 所帶來的復雜和難以維護,其實際就是用來抽象變化的(和開放-封閉原則是一個原理),只要在分析過程中我們發現需要在不同的時間運用不同類型的業務規則或者代碼中可能會出現很多變化,就可以考慮使用策略模式來處理這種變化。
策略模式通常的使用方法就是一個抽象策略類,若干具體策略類和一個Context類,同時Conetext類可以結合簡單工廠模式讓用戶與策略類完全解耦,比如可以向Context類的構造函數中傳入參數而不是策略類,然后在Conext的構造函數里用簡單工廠模式根據傳遞的參數初始化策略類,甚至還可以什么都不傳,定義一個默認策略供用戶使用(簡單工廠不一定是要一個單獨的類)。Conetext類中包含一個策略類的指針指向簡單工廠實例化出的具體策略類對象,還包含一個contextDeloy接口用于通過策略類指針去調用實例化出的具體策略類對象的接口,可以讓用戶面對Context的接口編程,而不與策略類接口直接耦合 ,方便策略類日后更改接口,同時還需要一個get接口,用于獲取簡單工廠中實例化出的對象。在業務邏輯層,我們先判斷簡單工廠模式實例化的具體對象是否為空,如果不為空,我們就可以通過contextDeloy接口去訪問實例化的具體策略類對象的接口。
其實之前的這篇博客https://blog.csdn.net/weixin_44049823/article/details/128907849中,計算器5.0版本就已經使用了策略模式,在這篇博客中,我們共實現了計算器的5個版本,最初使用的是簡單粗暴的if-else-if語句來判斷使用哪一種業務(運算),到5.0版本,我們抽象出了一個Operation類(策略類),然后又創建了4個具體類,加法運算、減法運算、乘法運算、除法運算類(4個具體策略類),最后創建了一個工廠類用于根據不同情況實例化不同運算類的對象,其實這之中的一個抽象策略類和4個具體策略類已經有策略模式的影子了,但是缺少了其精華Context類。
接下來我將用策略模式改寫之前的計算器5.0版本。
#include<iostream>
using namespace std;
#include<string>
//業務邏輯
//異常類用于處理異常情況
class opeException
{
public:
void getMessage()
{
cout << "您的輸入有誤!" << endl;
}
};
//運算類
class Operation
{
//判斷一個字符串是不是數字
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結合簡單工廠模式
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 << "請輸入左操作數:" << endl;
cin >> _strNum1;
cout << "請輸入右操作數:" << 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;
}
結合上一篇博客的5.0版本代碼可知,簡單工廠模式需要讓客戶端認識兩個類,而策略類只需要讓客戶端認識一個類即可,耦合更低。
總結策略模式的優缺點:
優點:
1、算法可以自由切換。
2、避免使用多重條件判斷。
3、擴展性良好。
缺點:
1、策略類會增多。
2、所有策略類都需要對外暴露。
注意事項:如果一個系統的策略多于四個,就需要考慮使用混合模式,解決策略類膨脹的問題。
原文鏈接:https://blog.csdn.net/weixin_44049823/article/details/129043252
- 上一篇:沒有了
- 下一篇:沒有了
相關推薦
- 2022-06-06 typescript中abstractClass(抽象類)、extends、abstract
- 2023-04-04 Golang利用casbin實現權限驗證詳解_Golang
- 2022-07-06 C#中的SQLCommand命令與DbTransaction事務處理_C#教程
- 2022-03-29 Android頂部標題欄的布局設計_Android
- 2022-12-22 利用C++求解八數碼問題實例代碼_C 語言
- 2022-02-02 Spring boot 項目目錄結構
- 2022-12-15 Rust實現一個表達式Parser小結_Rust語言
- 2022-07-09 springboot 視圖集成
- 欄目分類
-
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支