编程的法则 开闭原则(Open-Closed Principle, OCP)包括代码实践

编程的法则 开闭原则(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。每个具体形状类(如CircleRectangle)都继承自Shape并实现了getArea方法。当添加新形状(例如Triangle)时,只需创建一个新的派生类,而无需修改现有的代码。

示例:添加新功能而无需修改现有代码

继续上面的例子,假设现在需要添加一个新的形状,比如三角形(Triangle)。如果遵循开闭原则,只需添加一个新的Triangle类,而不需要修改已有的ShapeCircleRectangle类。

#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)是一种重要的设计思想,它鼓励开发者在设计系统时考虑未来的需求变化,应用这一原则时也需要权衡,避免过度设计带来的负面影响。

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

西笑生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值