C++设计模式:面向对象的八大设计原则之二

开放封闭原则(Open/Closed Principle,OCP)是面向对象设计中的一个重要原则,由 Bertrand Meyer 提出。该原则强调软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。也就是说,当需求发生变化时,我们应该通过扩展已有的代码来实现新功能,而不是直接修改原有的代码,这样可以降低代码的耦合度,提高系统的可维护性和可扩展性。

下面通过一个简单的 C++ 示例来详细讲解开放封闭原则。

示例场景

假设我们正在开发一个简单的图形绘制程序,该程序可以绘制不同类型的图形,如圆形和矩形。

违反开放封闭原则的实现

cpp 复制代码
#include <iostream>

// 图形基类
class Shape {public:

    virtual void draw() = 0;

    virtual ~Shape() {}};

// 圆形类
class Circle : public Shape {public:

    void draw() override {

        std::cout << "Drawing a circle." << std::endl;

    }};

// 矩形类
class Rectangle : public Shape {public:

    void draw() override {

        std::cout << "Drawing a rectangle." << std::endl;

    }};

// 图形绘制器类
class ShapeDrawer {public:

    void drawShape(Shape* shape) {

        shape->draw();

    }};

// 如果我们要添加一个新的图形类型,如三角形
class Triangle : public Shape {public:

    void draw() override {

        std::cout << "Drawing a triangle." << std::endl;

    }};

// 此时我们需要修改ShapeDrawer类来支持绘制三角形
class ShapeDrawer {public:

    void drawShape(Shape* shape) {

        if (dynamic_cast<Circle*>(shape)) {

            static_cast<Circle*>(shape)->draw();

        } else if (dynamic_cast<Rectangle*>(shape)) {

            static_cast<Rectangle*>(shape)->draw();

        } else if (dynamic_cast<Triangle*>(shape)) {

            static_cast<Triangle*>(shape)->draw();

        }

    }};

int main() {

    Circle circle;

    Rectangle rectangle;

    Triangle triangle;



    ShapeDrawer drawer;

    drawer.drawShape(&circle);

    drawer.drawShape(&rectangle);

    drawer.drawShape(&triangle);



    return 0;}

在这个实现中,当我们添加一个新的图形类型(如三角形)时,需要修改ShapeDrawer类的drawShape方法。这违反了开放封闭原则,因为我们直接修改了原有的代码。

遵循开放封闭原则的实现

cpp 复制代码
#include <iostream>

// 图形基类
class Shape {public:

    virtual void draw() = 0;

    virtual ~Shape() {}};

// 圆形类
class Circle : public Shape {public:

    void draw() override {

        std::cout << "Drawing a circle." << std::endl;

    }};

// 矩形类
class Rectangle : public Shape {public:

    void draw() override {

        std::cout << "Drawing a rectangle." << std::endl;

    }};

// 图形绘制器类
class ShapeDrawer {public:

    void drawShape(Shape* shape) {

        shape->draw();

    }};

// 如果我们要添加一个新的图形类型,如三角形
class Triangle : public Shape {public:

    void draw() override {

        std::cout << "Drawing a triangle." << std::endl;

    }};

int main() {

    Circle circle;

    Rectangle rectangle;

    Triangle triangle;



    ShapeDrawer drawer;

    drawer.drawShape(&circle);

    drawer.drawShape(&rectangle);

    drawer.drawShape(&triangle);



    return 0;}

在这个实现中,ShapeDrawer类的drawShape方法只依赖于Shape基类的抽象接口,而不依赖于具体的图形类。当我们添加一个新的图形类型(如三角形)时,只需要创建一个新的类继承自Shape基类,并实现draw方法,而不需要修改ShapeDrawer类的代码。这样就实现了对扩展开放,对修改关闭的原则。

总结

开放封闭原则是面向对象设计中的一个重要原则,它可以帮助我们构建更加灵活、可维护和可扩展的软件系统。在实际开发中,我们可以通过抽象和多态来实现开放封闭原则,尽量减少对原有代码的修改,而是通过扩展来实现新功能。

相关推荐
java叶新东老师11 分钟前
goland编写go语言导入自定义包出现: package xxx is not in GOROOT (/xxx/xxx) 的解决方案
开发语言·后端·golang
@蓝莓果粒茶22 分钟前
LeetCode第350题_两个数组的交集II
c++·python·学习·算法·leetcode·职场和发展·c#
檀越剑指大厂38 分钟前
【Python系列】Flask 应用中的主动垃圾回收
开发语言·python·flask
檀越剑指大厂1 小时前
【Python系列】使用 memory_profiler 诊断 Flask 应用内存问题
开发语言·python·flask
笠码1 小时前
JVM Java虚拟机
java·开发语言·jvm·垃圾回收
橙小花1 小时前
C语言:指针、变量指针与指针变量、数组指针与指针数组
c语言·开发语言
Cyanto1 小时前
MyBatis-Plus高效开发实战
java·开发语言·数据库
艾莉丝努力练剑2 小时前
【LeetCode&数据结构】二叉树的应用(二)——二叉树的前序遍历问题、二叉树的中序遍历问题、二叉树的后序遍历问题详解
c语言·开发语言·数据结构·学习·算法·leetcode·链表
wjs20242 小时前
XML 语法详解
开发语言
Jackilina_Stone3 小时前
【faiss】用于高效相似性搜索和聚类的C++库 | 源码详解与编译安装
android·linux·c++·编译·faiss