網站首頁 編程語言 正文
我們在做任何系統的時候,都不要指望系統一開始就完全確定需求,然后再也不發生變化,這是不現實,也是不科學的想法,既然需求是一定會發生變化的,那么如何在面對需求的變化時,設計的軟件可以相對容易修改,不至于說,新需求一來就要把整個程序都推倒重來呢?
開放-封閉原則可以做到這樣,所謂開放-封閉原則就是指軟件實體(類、函數、模塊等)應該可以擴展,但是不可以修改,即我們設計這個類的時候就盡量讓這個類足夠好,寫好了就不要去修改了,原來的代碼能不動則不動,如果新需求來,我們增加一些類就完事了。面對需求的改變,對程序的改動是通過增加新代碼進行的,而不是更改現有的代碼,這就是開放-封閉原則的精神所在。
在我們最初編寫代碼時,假設變化不會發生。當變化發生時,我們將創建抽象來隔離以后發生的同類變化。
在之前的這篇博客中,https://blog.csdn.net/weixin_44049823/article/details/128907849,我們實現了計算器的5個版本,這其中就運用了開放-封閉原則,這里,我們通過該篇博客實現的2.0版本和4.0版本來學習開放-封閉原則。
2.0版本:
#include<iostream>
using namespace std;
#include<string>
class opeException
{
public:
void getMessage()
{
cout << "您的輸入有誤!" << endl;
}
};
//判斷一個字符串是不是數字
bool isStringNum(string& s)
{
bool flag = true;
for (auto e : s)
if (!isdigit(e))
{
flag = false;
break;
}
return flag;
}
int main()
{
string num1 = "0";
string num2 = "0";
string ope = " ";
try
{
cout << "請輸入左操作數:" << endl;
cin >> num1;
if (!isStringNum(num1))
throw opeException();
cout << "請輸入右操作數:" << endl;
cin >> num2;
if (!isStringNum(num2))
throw opeException();
cout << "請輸入操作符" << endl;
cin >> ope;
if (ope != "+" && ope != "-" && ope != "*" && ope != "/")
throw opeException();
if (ope == "+")
{
cout<< stoi(num1) + stoi(num2)<<endl;
}
else if (ope == "-")
{
cout << stoi(num1) - stoi(num2) << endl;
}
else if (ope == "*")
{
cout << stoi(num1) * stoi(num2) << endl;
}
else if (ope == "/")
{
if (stoi(num2) != 0)
{
cout << stoi(num1) / stoi(num2) << endl;
}
else
cout << "除數不能為0" << endl;
}
}
catch (opeException ex)
{
ex.getMessage();
}
return 0;
}
在計算器2.0版本中,如果我們要增加開平方、平方、立方等運算,需要對代碼進行大量修改,這顯然不滿足開放-封閉原則,可維護性很差,面對這些可能的變化,在4.0版本的代碼中將各種具體運算,比如加減乘除分別抽象成為加法類、減法類、乘法類、除法類,這樣如果我們需要增加一些運算,面對這些變化,我們只需要再創建相應的運算類即可。
4.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() = 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;
}
};
//界面邏輯
int main()
{
try
{
string _strNum1 = " ";
string _strNum2 = " ";
string _ope = " ";
cout << "請輸入左操作數:" << endl;
cin >> _strNum1;
cout << "請輸入右操作數:" << endl;
cin >> _strNum2;
cout << "請輸入操作符:" << endl;
cin >> _ope;
if (_ope == "+")
{
addOperation addoperation(_strNum1, _strNum2, _ope);
cout << addoperation.getResult() << endl;
}
else if (_ope == "-")
{
subOperation suboperation(_strNum1, _strNum2, _ope);
cout << suboperation.getResult() << endl;
}
else if (_ope == "*")
{
mulOperation muloperation(_strNum1, _strNum2, _ope);
cout << muloperation.getResult() << endl;
}
else if (_ope == "/")
{
divOperation muloperation(_strNum1, _strNum2, _ope);
cout << muloperation.getResult() << endl;
}
else
cout << "您的輸入有誤!" << endl;
}
catch (opeException ex)
{
cout << "您的輸入有誤" << endl;
}
return 0;
}
當然,并不是什么時候應對變化都是容易的。我們希望的是在開發工作展開不久就知道可能發生的變化。查明可能發生的變化所等待的時間越長,要創建正確的抽象就越困難。比如,如果加減運算都在很多地方應用了,再考慮抽象、考慮分離,就很困難。
開放-封閉原則是面向對象設計的核心所在。遵循這個原則可以帶來面向對象技術所聲稱的巨大好處,也就是可維護、可擴展、可復用、靈活性好。開發人員應該僅對程序中呈現出頻繁變化的那些部分做出抽象,然而,對于應用程序中的每個部分都刻意地進行抽象同樣不是一個好主意。拒絕不成熟的抽象和抽象本身一樣重要。
原文鏈接:https://blog.csdn.net/weixin_44049823/article/details/129063620
- 上一篇:沒有了
- 下一篇:沒有了
相關推薦
- 2022-11-04 ASP.NET?MVC解決上傳圖片臟數據的方法_實用技巧
- 2022-11-27 C語言移除元素的三種思路講解_C 語言
- 2022-12-29 R語言中dnorm,pnorm,qnorm和rnorm的區別淺析_R語言
- 2022-09-01 ASP.NET輕量級MVC框架Nancy的基本用法_實用技巧
- 2023-03-22 Python裝飾器使用方法全面梳理_python
- 2022-07-19 Linux:配置本地yum源倉庫
- 2022-10-03 利用正則表達式校驗金額最多保留兩位小數實例代碼_正則表達式
- 2022-11-03 C/C++預處理淺析使用形式_C 語言
- 欄目分類
-
- 最近更新
-
- 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同步修改后的遠程分支