2023年8月27日,周日下午
我覺得我的這篇博客還是寫得很不錯(cuò)的,哈哈哈。
目錄
- 概述
- 舉例說明
- 用開放-封閉原則重構(gòu)
概述
開放-封閉原則(Open-Closed Principle,OCP)是面向?qū)ο笤O(shè)計(jì)中的一個(gè)重要原則,也是許多設(shè)計(jì)模式的基礎(chǔ)。它由Bertrand Meyer在他的書《面向?qū)ο筌浖?gòu)造》中提出,并被廣泛應(yīng)用于軟件開發(fā)中。
開放-封閉原則的核心思想是:軟件實(shí)體(類、模塊、函數(shù)等)應(yīng)該對擴(kuò)展開放,對修改封閉。換句話說,當(dāng)需要修改一個(gè)軟件實(shí)體時(shí),應(yīng)該通過擴(kuò)展它的行為,而不是修改它的源代碼。
這個(gè)原則的目標(biāo)是實(shí)現(xiàn)軟件設(shè)計(jì)的穩(wěn)定性和可維護(hù)性。通過遵循開放-封閉原則,我們可以減少修改已有代碼的需求,從而降低了引入新錯(cuò)誤的風(fēng)險(xiǎn),并提高了代碼的可復(fù)用性。
實(shí)現(xiàn)開放-封閉原則的關(guān)鍵是使用抽象和多態(tài)。通過定義抽象的接口或基類,可以將代碼與特定的實(shí)現(xiàn)分離開來。這樣,在需要變更行為時(shí),我們只需要?jiǎng)?chuàng)建新的實(shí)現(xiàn)類并基于抽象進(jìn)行擴(kuò)展,而不需要修改已有的代碼。
舉例說明
假如有一天,公司要我寫一個(gè)計(jì)算圓的面積的函數(shù)getArea
#include <iostream>
// 計(jì)算圓的面積
double getArea(double radius) {
return 3.14159 * radius * radius;
}
int main() {
// 計(jì)算面積
double area = getArea(3);
// 輸出面積
std::cout << "area: " << area << std::endl;
return 0;
}
這很簡單,是不是?
但是后來公司要求這個(gè)getArea函數(shù)要增加計(jì)算正方形的面積的功能,
假設(shè)我不懂開放-封閉原則,那么我只能老老實(shí)實(shí)修改getArea函數(shù)內(nèi)部的代碼
#include <iostream>
// 計(jì)算面積
double getArea(double num,std::string thing) {
if(thing=="圓形")
return 3.14159 * num * num;
if(thing=="正方形")
return num*num;
}
int main() {
// 計(jì)算面積
double area1 = getArea(3,"圓形");
double area2=getArea(4,"正方形");
// 輸出面積
std::cout << "圓形面積: " << area1 << std::endl;
std::cout << "正方形面積: " << area2 << std::endl;
return 0;
}
雖然我也完成了任務(wù),但可以看到getArea函數(shù)變得復(fù)雜了:參數(shù)由1個(gè)變成2個(gè);內(nèi)部的實(shí)現(xiàn)代碼也更多了。
但是任務(wù)還沒結(jié)束,后來公司又讓我給getArea函數(shù)添加計(jì)算長方形的功能
#include <iostream>
// 計(jì)算面積
double getArea(double num1,double num2,std::string thing) {
if(thing=="圓形")
return 3.14159 * num1 * num1;
if(thing=="正方形")
return num1*num1;
if(thing=="長方形")
return num1*num2;
}
int main() {
// 計(jì)算面積
double area1 = getArea(3,0,"圓形");
double area2=getArea(4,0,"正方形");
double area3=getArea(4,3,"長方形");
// 輸出面積
std::cout << "圓形面積: " << area1 << std::endl;
std::cout << "正方形面積: " << area2 << std::endl;
std::cout << "長方形面積: " << area3 << std::endl;
return 0;
}
可以看出來,我的getArea函數(shù)不僅變得更加難以理解,而且變得更加復(fù)雜了:參數(shù)由2個(gè)變成3個(gè),而且內(nèi)部代碼實(shí)現(xiàn)也變多了。
接下來就不用寫,照這么寫下去,隨著需求的增多,getArea函數(shù)只會(huì)變得越來越復(fù)雜和難以理解。
用開放-封閉原則重構(gòu)
不難看出,在getArea中不變的是要返回一個(gè)面積,不斷變化的是不同圖形的計(jì)算方法,
所以可以封閉getArea的”返回一個(gè)面積“,而開放”計(jì)算方法“。
我把所有圖形抽象成一個(gè)Shape抽象類,要求所有Shape抽象類的派生類都必須提供一個(gè)返回面積的接口。至于這些派生類怎么實(shí)現(xiàn)父類Shape要求的返回面積的接口,就各顯神通、因地制宜了,此之謂”開放擴(kuò)展“
而getArea函數(shù)只需雷打不動(dòng)地調(diào)用Shape類的派生類的返回面積的接口就可以了,此之謂”封閉修改“。
#include <iostream>
// 抽象基類,用于表示圖形形狀
class Shape {
public:
virtual double area() const = 0;
};
// 具體的圖形形狀:矩形
class Rectangle : public Shape {
public:
double width;
double height;
Rectangle(double w, double h) : width(w), height(h) {}
double area() const override {
return width * height;
}
};
// 具體的圖形形狀:圓形
class Circle : public Shape {
public:
double radius;
Circle(double r) : radius(r) {}
double area() const override {
return 3.14159 * radius * radius;
}
};
// 計(jì)算所有圖形的總面積
double getArea(const Shape* shape) {
return shape->area();
}
int main() {
// 創(chuàng)建矩形和圓形對象
Circle circle(3);
Rectangle rect1(4, 4);
Rectangle rect2(4, 3);
// 計(jì)算總面積
double area1 = getArea(&circle);
double area2=getArea(&rect1);
double area3=getArea(&rect2);
// 輸出面積
std::cout << "圓形面積: " << area1 << std::endl;
std::cout << "正方形面積: " << area2 << std::endl;
std::cout << "長方形面積: " << area3 << std::endl;
return 0;
}
可以看到,無論公司要求增加什么圖形的計(jì)算面積功能,都不需要修改getArea函數(shù),
只需要增加一個(gè)繼承自Shape類的派生類就可以了,文章來源:http://www.zghlxwxcb.cn/news/detail-684679.html
不信的話,你們可以再添加一個(gè)計(jì)算梯形的面積試試,就當(dāng)作一個(gè)小作業(yè)。文章來源地址http://www.zghlxwxcb.cn/news/detail-684679.html
到了這里,關(guān)于【C++設(shè)計(jì)模式】開放-封閉原則的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!