C++開放封閉原則示例解析
我們在做任何系統(tǒng)的時(shí)候,都不要指望系統(tǒng)一開始就完全確定需求,然后再也不發(fā)生變化,這是不現(xiàn)實(shí),也是不科學(xué)的想法,既然需求是一定會(huì)發(fā)生變化的,那么如何在面對需求的變化時(shí),設(shè)計(jì)的軟件可以相對容易修改,不至于說,新需求一來就要把整個(gè)程序都推倒重來呢?
開放-封閉原則可以做到這樣,所謂開放-封閉原則就是指軟件實(shí)體(類、函數(shù)、模塊等)應(yīng)該可以擴(kuò)展,但是不可以修改,即我們設(shè)計(jì)這個(gè)類的時(shí)候就盡量讓這個(gè)類足夠好,寫好了就不要去修改了,原來的代碼能不動(dòng)則不動(dòng),如果新需求來,我們增加一些類就完事了。面對需求的改變,對程序的改動(dòng)是通過增加新代碼進(jìn)行的,而不是更改現(xiàn)有的代碼,這就是開放-封閉原則的精神所在。
在我們最初編寫代碼時(shí),假設(shè)變化不會(huì)發(fā)生。當(dāng)變化發(fā)生時(shí),我們將創(chuàng)建抽象來隔離以后發(fā)生的同類變化。
在之前的這篇博客中,https://blog.csdn.net/weixin_44049823/article/details/128907849,我們實(shí)現(xiàn)了計(jì)算器的5個(gè)版本,這其中就運(yùn)用了開放-封閉原則,這里,我們通過該篇博客實(shí)現(xiàn)的2.0版本和4.0版本來學(xué)習(xí)開放-封閉原則。
2.0版本:
#include<iostream> using namespace std; #include<string> class opeException { public: void getMessage() { cout << "您的輸入有誤!" << endl; } }; //判斷一個(gè)字符串是不是數(shù)字 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 << "請輸入左操作數(shù):" << endl; cin >> num1; if (!isStringNum(num1)) throw opeException(); cout << "請輸入右操作數(shù):" << 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 << "除數(shù)不能為0" << endl; } } catch (opeException ex) { ex.getMessage(); } return 0; }
在計(jì)算器2.0版本中,如果我們要增加開平方、平方、立方等運(yùn)算,需要對代碼進(jìn)行大量修改,這顯然不滿足開放-封閉原則,可維護(hù)性很差,面對這些可能的變化,在4.0版本的代碼中將各種具體運(yùn)算,比如加減乘除分別抽象成為加法類、減法類、乘法類、除法類,這樣如果我們需要增加一些運(yùn)算,面對這些變化,我們只需要再創(chuàng)建相應(yīng)的運(yùn)算類即可。
4.0版本:
#include<iostream> using namespace std; #include<string> //業(yè)務(wù)邏輯 //異常類用于處理異常情況 class opeException { public: void getMessage() { cout << "您的輸入有誤!" << endl; } }; //運(yùn)算類 class Operation { //判斷一個(gè)字符串是不是數(shù)字 bool isStringNum(string& s) { bool flag = true; for (auto e : s) if (!(isdigit(e))) { flag = false; break; } return flag; } protected: //判斷輸入的操作數(shù)和操作符是否有誤 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; }; //加法運(yùn)算類 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; } }; //減法運(yùn)算類 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; } }; //乘法運(yùn)算類 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; } }; //除法運(yùn)算類 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 << "請輸入左操作數(shù):" << endl; cin >> _strNum1; cout << "請輸入右操作數(shù):" << 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; }
當(dāng)然,并不是什么時(shí)候應(yīng)對變化都是容易的。我們希望的是在開發(fā)工作展開不久就知道可能發(fā)生的變化。查明可能發(fā)生的變化所等待的時(shí)間越長,要?jiǎng)?chuàng)建正確的抽象就越困難。比如,如果加減運(yùn)算都在很多地方應(yīng)用了,再考慮抽象、考慮分離,就很困難。
開放-封閉原則是面向?qū)ο笤O(shè)計(jì)的核心所在。遵循這個(gè)原則可以帶來面向?qū)ο蠹夹g(shù)所聲稱的巨大好處,也就是可維護(hù)、可擴(kuò)展、可復(fù)用、靈活性好。開發(fā)人員應(yīng)該僅對程序中呈現(xiàn)出頻繁變化的那些部分做出抽象,然而,對于應(yīng)用程序中的每個(gè)部分都刻意地進(jìn)行抽象同樣不是一個(gè)好主意。拒絕不成熟的抽象和抽象本身一樣重要。
到此這篇關(guān)于C++開放封閉原則示例解析的文章就介紹到這了,更多相關(guān)C++開放封閉原則內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++map,set,multiset,multimap詳細(xì)解析
在C++標(biāo)準(zhǔn)模板庫(STL)中,容器分為關(guān)聯(lián)式容器和序列式容器兩大類,關(guān)聯(lián)式容器主要包括set、map、multiset和multimap,通過索引來訪問元素,本文給大家介紹C++?map,set,multiset,multimap的相關(guān)知識,感興趣的朋友跟隨小編一起看看吧2024-09-09利用C語言實(shí)現(xiàn)順序表的實(shí)例操作
順序表是線性表中的一種重要的數(shù)據(jù)結(jié)構(gòu),也是最基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu),所以他不僅是學(xué)習(xí)中的重點(diǎn),也是應(yīng)用開發(fā)非常常用的一種數(shù)據(jù)結(jié)構(gòu)。這篇文章介紹如何利用C語言實(shí)現(xiàn)順序表。2016-08-08C++實(shí)現(xiàn)第K順序統(tǒng)計(jì)量的求解方法
這篇文章主要介紹了C++實(shí)現(xiàn)第K順序統(tǒng)計(jì)量的求解方法,很有借鑒價(jià)值的算法,需要的朋友可以參考下2014-08-08STL區(qū)間成員函數(shù)及區(qū)間算法總結(jié)
這篇文章主要匯總介紹了STL區(qū)間成員函數(shù)及區(qū)間算法,有需要的小伙伴可以參考下。2015-07-07C++實(shí)現(xiàn)單例模式的自動(dòng)釋放
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)單例模式的自動(dòng)釋放,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06