当前位置: 首页 > news >正文

C++设计模式:类间关系

类封装了数据和行为,是面向对象的重要组成部分,它是具有相同属性、操作、关系的对象集合的总称。在系统中,每个类都具有一定的职责,职责指的是类要完成什么样子的功能,要承担什么样子的义务。一个类可以有多种职责,但是设计得好的类一般只有一种职责。

类与类之间的关系

继承关系

继承也叫作泛化(Generalization),子类(派生类)继承父类(基类)的属性和方法,并可扩展或重写父类功能。

C++ 中没有专门的 “接口” 关键字,通常用纯虚基类模拟接口,子类通过 public 继承该纯虚类并实现其所有纯虚函数。

class Bird
{
public:string getName(){return m_name;}void setName(string name){m_name = name;}virtual void fly() {}virtual void eat() {}
protected:string m_sex;string m_name;
};class Cuckoo : public Bird
{
public:void fly() override{cout << "我拍打翅膀飞行..." << endl;}void eat() override{cout << "我喜欢吃肉肉的小虫子..." << endl;}
};class Eagle : public Bird
{
public:void fly() override{cout << "我展翅翱翔..." << endl;}void eat() override{cout << "我喜欢吃小动物..." << endl;}
};

 组合关系

组合(Composition)表示 “整体 - 部分” 关系,部分完全依赖整体存在(强包含)。

部分不能脱离整体独立存在,整体的生命周期决定部分的生命周期(整体创建时部分被创建,整体销毁时部分也被销毁),部分只能属于一个整体。
例如人和心脏:心脏是人的一部分,人死亡后心脏也不再独立存在。

class Heart {
public:void beat() {}
};
class Person {
private:Heart heart; // 组合关系(部分作为成员变量,随整体创建/销毁)
public:Person() : heart() {} // 构造时创建心脏
};

 聚合关系

聚合(Aggregation)表示 “整体 - 部分” 关系,部分可脱离整体独立存在(弱包含)。

整体通过成员变量持有部分的指针 / 引用,整体包含部分,但部分的生命周期不由整体控制,部分可属于多个整体。

比如公司和员工:员工是公司的一部分,但员工可离职(脱离公司存在)。

class Employee {};
class Company {
private:std::vector<Employee*> employees; // 聚合员工(部分)
public:void addEmployee(Employee* e) {employees.push_back(e);}
};

关联关系

表示两个类之间存在长期、稳定的连接,通常体现为一个类持有另一个类的对象引用(或指针)。

关系可单向或双向(如 A 关联 B,或 A 与 B 相互关联),类之间生命周期相互独立,关联不影响对象的创建与销毁。

单向关联

单向关联指的是关联只有一个方向,比如每个孩子都拥有一个Parent,其代码实现为:

class Parent
{
};class Child
{
private:Parent m_father;
};
双向关联

现实生活中每个孩子都有父母,每个父母同样有自己的孩子,如果想要通过类来描述这样的亲情关系,代码如下:

class Parent
{
private:Child* m_son;
};class Child
{
private:Parent* m_father;
};
自关联

自关联指的就是当前类中包含一个自身类型的对象成员,这在链表中非常常见,单向链表中都会有一个指向自身节点类型的后继指针成员,而双向链表中会包含一个指向自身节点类型的前驱指针和一个指向自身节点类型的后继指针。就以双向链表节点类为例,它的C++写法为:

class Node 
{
private:void* m_data;Node* m_prev;Node* m_next;
};

 依赖关系

表示一个类(依赖方)在执行特定操作时,临时需要另一个类(被依赖方)的协助,是一种短期的 “使用” 关系。

通常通过方法参数、局部变量或静态方法调用体现,无长期持有关系,操作结束后依赖消失。

例如计算器计算时需要临时使用数字Number对象:

class Number {
public:int value;
};
class Calculator {
public:// 通过参数依赖 Numberint add(Number a, Number b) { return a.value + b.value; }
};

总结

类之间的关系强弱顺序是这样的:继承(含接口实现) >  组合  >  聚合  >  关联  >  依赖。

在实际设计中,应优先使用低耦合关系(如关联、聚合、组合),避免过度依赖继承,以提高代码的灵活性和可维护性。

http://www.xdnf.cn/news/1301689.html

相关文章:

  • 企业级时序数据库选型指南:从传统架构向智能时序数据管理的转型之路
  • Flinksql bug: Heartbeat of TaskManager with id container_XXX timed out.
  • gitee_流水线搭配 Dockerfile 部署vue项目
  • MetaFox官方版:轻松转换视频,畅享MKV格式的便捷与高效
  • 【Linux基础知识系列】第九十六篇 - 使用history命令管理命令历史
  • std::set_symmetric_difference
  • 4. 图像识别模型与训练策略
  • 解锁AI大模型:Prompt工程全面解析
  • Spring MVC ModelAndView 详解
  • Linux网络基础(一)
  • 【计算机视觉与深度学习实战】01基于直方图优化的图像去雾技术
  • Python入门第3课:Python中的条件判断与循环语句
  • 电商架构测试体系:ZKmall开源商城筑牢高并发场景下的系统防线
  • Dijkstra与Floyd求最短路算法简介
  • 【JAVA高级】实现word转pdf 实现,源码概述。深坑总结
  • Vue3 学习教程,从入门到精通,Axios 在 Vue 3 中的使用指南(37)
  • 在Ubuntu 22.04上安装远程桌面服务
  • 关于C++的#include的超超超详细讲解
  • 为什么 /deep/ 现在不推荐使用?
  • 稳定且高效:GSPO如何革新大型语言模型的强化学习训练?
  • Webpack详解
  • 思考:高速场景的行星轮混动效率如何理解
  • 解决Electron透明窗口点击不影响其他应用
  • 启动electron桌面项目控制台输出中文时乱码解决
  • 下载及交叉编译zlib库,记录
  • 解决ECharts图表上显示的最小刻度不是设置的min值的问题
  • 从源码到可执行文件:hello.c 的二进制之旅
  • 【Golang】:数据类型
  • Wi-Fi 与蜂窝网络(手机网络)的核心区别,以及 Wi-Fi 技术未来的发展方向
  • Redisson分布式锁实战指南:原理、用法与项目案例