C++ 开闭原则
C++中的开闭原则(Open-Closed Principle, OCP)是面向对象设计的核心原则之一,其核心思想是:软件实体(类、模块、函数等)应对扩展开放,对修改关闭。这意味着当需求变化时,应通过新增代码(如新增类或方法)来扩展功能,而非直接修改现有代码,从而降低维护成本并提高系统稳定性。
代码示例:通过抽象基类实现开闭原则
以下是一个计算器程序的改进案例,展示了如何从违反开闭原则的设计改进为符合原则的设计。
1. 违反开闭原则的原始设计
原始计算器类直接通过条件判断处理不同运算,新增运算需修改getResult方法,违反开闭原则。
#include <iostream>
#include <string>
using namespace std;
class Calculator {
public:
Calculator(int a, int b, string op) : a(a), b(b), op(op) {}
int getResult() {
if (op == "+") return a + b;
else if (op == "-") return a - b;
else if (op == "*") return a * b;
else if (op == "/") return a / b;
// 新增运算(如取模%)需修改此方法,违反OCP
return 0;
}
private:
int a, b;
string op;
};
int main() {
Calculator calc(10, 5, "+");
cout << "Result: " << calc.getResult() << endl; // 输出15
return 0;
}
问题:新增运算(如取模%)需直接修改getResult方法,可能引入错误,且需重新测试所有分支。
2. 符合开闭原则的改进设计
通过抽象基类Operation定义运算接口,具体运算由派生类实现。新增运算时,仅需新增派生类,无需修改现有代码。
#include <iostream>
#include <memory> // 使用智能指针管理动态内存
using namespace std;
// 抽象基类:定义运算接口
class Operation {
public:
virtual int calculate(int a, int b) = 0;
virtual ~Operation() = default; // 虚析构函数确保派生类对象被正确销毁
};
// 具体运算类:加法
class AddOperation : public Operation {
public:
int calculate(int a, int b) override { return a + b; }
};
// 具体运算类:减法
class SubtractOperation : public Operation {
public:
int calculate(int a, int b) override { return a - b; }
};
// 具体运算类:乘法(新增运算示例)
class MultiplyOperation : public Operation {
public:
int calculate(int a, int b) override { return a * b; }
};
// 计算器类:通过接口调用具体运算
class Calculator {
public:
Calculator(unique_ptr<Operation> op) : op(move(op)) {}
int getResult(int a, int b) {
return op->calculate(a, b);
}
private:
unique_ptr<Operation> op; // 使用智能指针管理运算对象
};
int main() {
// 测试加法
Calculator addCalc(make_unique<AddOperation>());
cout << "Addition: " << addCalc.getResult(10, 5) << endl; // 输出15
// 测试减法
Calculator subCalc(make_unique<SubtractOperation>());
cout << "Subtraction: " << subCalc.getResult(10, 5) << endl; // 输出5
// 新增乘法运算,无需修改Calculator或Operation类
Calculator mulCalc(make_unique<MultiplyOperation>());
cout << "Multiplication: " << mulCalc.getResult(10, 5) << endl; // 输出50
return 0;
}
改进设计的优势
- 对扩展开放:新增运算(如除法、取模)时,仅需定义新的派生类(如
DivideOperation),无需修改现有代码。 - 对修改关闭:现有运算类(如
AddOperation)和计算器类Calculator的代码无需变动,降低了引入错误的风险。 - 符合SOLID原则:与依赖倒置原则(DIP)结合,高层模块(
Calculator)依赖抽象(Operation),而非具体实现。
关键点总结
- 抽象基类:定义接口,约束派生类行为。
- 多态调用:通过基类指针或引用调用派生类方法,实现运行时绑定。
- 智能指针:使用
unique_ptr管理动态内存,避免内存泄漏。
通过这种设计,系统能够灵活应对需求变化,同时保持代码的稳定性和可维护性。
浙公网安备 33010602011771号