聚合,组合,依赖

1. 聚合:

是关联关系的一种特例,体现的是整体与部分拥有的关系,即 has-a 的关系,此时整体与部分之间可以分离

//学校
class School
{
};

//学生
class Student
{
private:
  School* ps;
};
可以看到 Student 类中包含了一个 School 类的对象指针,而且在创建一个Student 类对象时一定要对指针进行初始化,就好像当你上学时一定会有一个学校!这个时候,我们可以说 Student 的每一个对象都有一个School 的属性来标识它是属于哪个学校的!
但是两者之间并不存在“同生共死”的关系,也就是说当这个学生不存在的时候,学校还是有的!

2. 组合:

也是关联关系的一种特例,体现在一种 contain - a 的关系,这种关系比聚合更强,整体与部分是不可分的。

//眼
class Eye
{
};

//鼻
class Nose
{
};

//头
class Head
{
private:
  Eye  m_eye;
  Nose m_nose;
};
一个head ,一定会有 eye,nose 等。一旦 head 不存在了,eye nose 也没存在的意义了。即 head 拥有这些对象类。

3. 依赖:

当一个对象负责构造另一个对象的实例,或者依赖另一个对象的服务时,这两个对象之间主要体现为依赖关系。

依赖关系表现在局部变量方法的参数,以及对静态方法的调用

//苹果刀
class Knife
{
public:
  paring(); //削东西
}

//苹果
class Apple
{
};

//学生
class Student
{
  void DoSomething();
  void Eat(Apple* a){...}
};

Student::DoSomething()
{
  Knife ke;
  ke.paring();
}

上面, 你不能把 apple 看成 student 的一种属性,不存在包含关系。试想哪个人一生下来就一定要吃苹果呢。

同样,student 每次做事 doSomething() 也不会只去削东西吧。

通过一个方法,并让 Apple 类指针做形参(引用也可以),这样子就实现了student 吃苹果的过程。为什么要用指针类型做形参?

因为 student 吃苹果并不只会影响 student 自己,当然苹果本身也会有一些变化,而这些变化都是通过传递过来的指针来间接调用 Apple 类的方法来实现的!


### 概念 - **聚合关系**:部分与整体之间是一种较弱的“拥有”关系。部分可以脱离整体存在,整体只是暂时性地包含或使用部分。例如,汽车和它的轮胎之间的关系可以被视为聚合关系,因为轮胎可以在没有汽车的情况下存在[^1]。 - **组合关系**:部分与整体之间存在强制性的生死关系。部分不能脱离整体单独存在,当整体被销毁时,它的所有部分也会随之被销毁。这种关系适用于那些不能独立存在的对象[^1]。 - **依赖关系**:是一种使用关系,一个类的实现需要另一个类的协助,是一种临时性的、偶然性的关系。在代码中,通常表现为一个类的方法使用另一个类的对象作为参数、局部变量或调用另一个类的静态方法等。 - **继承关系**:是一种“is - a”的关系,子类继承父类的属性和方法,并且可以对父类的方法进行重写或扩展。子类可以复用父类的代码,同时可以添加自己特有的属性和方法。 - **接口**:接口有两栏组成,第一栏的顶端加上《interface》后下方写接口名称,第二栏是接口方法。接口有自己的表示方法“实现”,虚线一端带空心三角形。接口是一种抽象类型,它定义了一组方法的签名,但没有具体的实现,任何实现该接口的类都必须实现接口中定义的所有方法[^4]。 ### 区别 - **聚合组合**:聚合关系中部分可以脱离整体独立存在,整体和部分的生命周期没有必然联系;而组合关系中部分的存在依赖于整体,整体的生命周期决定部分的生命周期[^1]。 - **聚合组合依赖**:聚合组合都是整体与部分的关系,是一种较为紧密的结构关系;而依赖一种使用关系,相对比较松散,不强调整体与部分的结构关系。 - **继承与聚合组合**:继承是一种“is - a”的关系,子类继承父类的特征;聚合组合是“has - a”的关系,强调对象之间的包含关系。继承具有较强的耦合性,子类依赖于父类的实现;聚合组合的耦合性相对较弱。 - **接口与继承**:继承是子类直接复用父类的代码和行为;而接口只定义了方法的签名,实现接口的类需要自己实现这些方法,接口实现了多态性,一个类可以实现多个接口,而继承通常只能有一个父类。 ### 应用 - **聚合关系**:适用于表示部分可以独立于整体存在的场景,如学校和学生的关系,学生可以独立于学校存在,学校暂时性地包含学生。 - **组合关系**:适用于部分不能独立存在的场景,如人和心脏的关系,心脏不能脱离人单独存在。 - **依赖关系**:在代码中,当一个类需要使用另一个类的功能时可以使用依赖关系。例如,一个日志记录类需要使用文件操作类来将日志写入文件。 - **继承关系**:当多个类具有共同的属性和方法时,可以使用继承来实现代码复用。例如,不同类型的汽车类可以继承自一个基类“汽车”,复用基类的属性和方法。 - **接口**:为了实现“开 - 闭原则”,在实际开发中一般定义接口,依赖于接口,依赖于抽象。例如,在一个电商系统中,不同的支付方式(如支付宝、微信支付)可以实现同一个支付接口。 ### 示例代码 ```python # 聚合关系示例 class Tire: def __init__(self): pass class Car: def __init__(self, tires): self.tires = tires tire1 = Tire() tire2 = Tire() car = Car([tire1, tire2]) # 组合关系示例 class Engine: def __init__(self): pass class Car2: def __init__(self): self.engine = Engine() # 依赖关系示例 class FileWriter: def write_to_file(self, content): print(f"Writing {content} to file") class Logger: def __init__(self, file_writer): self.file_writer = file_writer def log(self, message): self.file_writer.write_to_file(message) file_writer = FileWriter() logger = Logger(file_writer) logger.log("This is a log message") # 继承关系示例 class Animal: def eat(self): print("Animal is eating") class Dog(Animal): def bark(self): print("Dog is barking") dog = Dog() dog.eat() dog.bark() # 接口示例(Python 中用抽象基类模拟接口) from abc import ABC, abstractmethod class PaymentInterface(ABC): @abstractmethod def pay(self, amount): pass class AlipayPayment(PaymentInterface): def pay(self, amount): print(f"Paying {amount} with Alipay") payment = AlipayPayment() payment.pay(100) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值