编程的法则 开闭原则(Open-Closed Principle, OCP)包括代码实践
flyfish
2017-07-18
2024-07-19
开闭原则(Open-Closed Principle, OCP)是软件设计中的一项基本原则,提出软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。也就是说,应该能够通过扩展软件的行为来增加新功能,而不需要修改现有代码。这有助于提高软件的可维护性和可扩展性。
以下是一个用C++代码来展示开闭原则的例子:
假设有一个几何形状类层次结构,最初只有圆形(Circle)和矩形(Rectangle)类,并且希望能够计算这些形状的面积。
不符合开闭原则的实现
在不符合开闭原则的实现中,可能会创建一个包含所有形状的AreaCalculator
类。每当需要添加新形状时,都需要修改AreaCalculator
类。
例如添加新形状(例如三角形、椭圆等)时,都需要修改AreaCalculator
类的代码。
#include <iostream>
#include <vector>
#include <cmath>
const double M_PI = 3.1415926535897;
class Circle {
public:
Circle(double radius) : radius_(radius) {}
double getRadius() const { return radius_; }
private:
double radius_;
};
class Rectangle {
public:
Rectangle(double width, double height) : width_(width), height_(height) {}
double getWidth() const { return width_; }
double getHeight() const { return height_; }
private:
double width_;
double height_;
};
class AreaCalculator {
public:
double calculateArea(const Circle& circle) const {
return M_PI * std::pow(circle.getRadius(), 2);
}
double calculateArea(const Rectangle& rectangle) const {
return rectangle.getWidth() * rectangle.getHeight();
}
};
int main() {
Circle circle(5);
Rectangle rectangle(4, 6);
AreaCalculator calculator;
std::cout << "Circle area: " << calculator.calculateArea(circle) << std::endl;
std::cout << "Rectangle area: " << calculator.calculateArea(rectangle) << std::endl;
return 0;
}
#include <iostream>
#include <vector>
#include <memory>
#include <cmath>
const double M_PI = 3.1415926535897;
class Shape {
public:
virtual ~Shape() = default;
virtual double getArea() const = 0;
};
class Circle : public Shape {
public:
Circle(double radius) : radius_(radius) {}
double getArea() const override {
return M_PI * std::pow(radius_, 2);
}
private:
double radius_;
};
class Rectangle : public Shape {
public:
Rectangle(double width, double height) : width_(width), height_(height) {}
double getArea() const override {
return width_ * height_;
}
private:
double width_;
double height_;
};
int main() {
std::vector<std::unique_ptr<Shape>> shapes;
shapes.emplace_back(std::make_unique<Circle>(5));
shapes.emplace_back(std::make_unique<Rectangle>(4, 6));
for (const auto& shape : shapes) {
std::cout << "Area: " << shape->getArea() << std::endl;
}
return 0;
}
符合开闭原则的实现
为了遵循开闭原则,可以使用多态性。定义一个抽象基类Shape
,并为每个具体形状创建派生类。这种方式允许通过扩展添加新形状,而无需修改现有代码。例如添加新形状(例如三角形、椭圆等)时,而无需修改现有代码。
#include <iostream>
#include <vector>
#include <memory>
#include <cmath>
class Shape {
public:
virtual ~Shape() = default;
virtual double getArea() const = 0;
};
class Circle : public Shape {
public:
Circle(double radius) : radius_(radius) {}
double getArea() const override {
return M_PI * std::pow(radius_, 2);
}
private:
double radius_;
};
class Rectangle : public Shape {
public:
Rectangle(double width, double height) : width_(width), height_(height) {}
double getArea() const override {
return width_ * height_;
}
private:
double width_;
double height_;
};
int main() {
std::vector<std::unique_ptr<Shape>> shapes;
shapes.emplace_back(std::make_unique<Circle>(5));
shapes.emplace_back(std::make_unique<Rectangle>(4, 6));
for (const auto& shape : shapes) {
std::cout << "Area: " << shape->getArea() << std::endl;
}
return 0;
}
在这个符合开闭原则的实现中,Shape
类是一个抽象基类,定义了一个纯虚函数getArea
。每个具体形状类(如Circle
和Rectangle
)都继承自Shape
并实现了getArea
方法。当添加新形状(例如Triangle
)时,只需创建一个新的派生类,而无需修改现有的代码。
示例:添加新功能而无需修改现有代码
继续上面的例子,假设现在需要添加一个新的形状,比如三角形(Triangle)。如果遵循开闭原则,只需添加一个新的Triangle
类,而不需要修改已有的Shape
、Circle
或Rectangle
类。
#include <iostream>
#include <vector>
#include <memory>
#include <cmath>
const double M_PI = 3.1415926535897;
class Shape {
public:
virtual ~Shape() = default;
virtual double getArea() const = 0;
};
class Circle : public Shape {
public:
Circle(double radius) : radius_(radius) {}
double getArea() const override {
return M_PI * std::pow(radius_, 2);
}
private:
double radius_;
};
class Rectangle : public Shape {
public:
Rectangle(double width, double height) : width_(width), height_(height) {}
double getArea() const override {
return width_ * height_;
}
private:
double width_;
double height_;
};
class Triangle : public Shape {
public:
Triangle(double base, double height) : base_(base), height_(height) {}
double getArea() const override {
return 0.5 * base_ * height_;
}
private:
double base_;
double height_;
};
int main() {
std::vector<std::unique_ptr<Shape>> shapes;
shapes.emplace_back(std::make_unique<Circle>(5));
shapes.emplace_back(std::make_unique<Rectangle>(4, 6));
shapes.emplace_back(std::make_unique<Triangle>(3, 4));
for (const auto& shape : shapes) {
std::cout << "Area: " << shape->getArea() << std::endl;
}
return 0;
}
开闭原则(Open-Closed Principle, OCP)是一种重要的设计思想,它鼓励开发者在设计系统时考虑未来的需求变化,应用这一原则时也需要权衡,避免过度设计带来的负面影响。