截至目前,我们已经探讨了三种对象间关系:组合(composition)、聚合(aggregation)和关联(association)。我们把最简单的一种留到最后——依赖(dependency)。
在日常语境中,我们用“依赖”一词表示某个对象为了完成特定任务而需要另一个对象。例如,如果你摔断了脚,你就依赖拐杖行走(但除此之外并不依赖)。花朵依赖蜜蜂授粉以结果或繁衍(但除此之外并不依赖)。
在软件中,依赖发生在一个对象调用另一个对象的功能以完成特定任务之时。这是一种比关联更弱的关系,但任何对被依赖对象的修改都可能破坏依赖方(调用方)的功能。依赖始终是单向关系。
一个你已多次见过的依赖示例是 std::ostream。我们编写的类使用 std::ostream 仅用于向控制台输出信息,除此之外并无其他关系。
示例
#include <iostream>
class Point
{
private:
    double m_x{};
    double m_y{};
    double m_z{};
public:
    Point(double x = 0.0, double y = 0.0, double z = 0.0)
        : m_x{x}, m_y{y}, m_z{z}
    {
    }
    friend std::ostream& operator<<(std::ostream& out, const Point& point);
    // Point 在此处依赖 std::ostream
};
std::ostream& operator<<(std::ostream& out, const Point& point)
{
    // 由于 operator<< 是 Point 的友元,可直接访问其成员
    out << "Point(" << point.m_x << ", " << point.m_y << ", " << point.m_z << ")";
    return out;
}
int main()
{
    Point point1{ 2.0, 3.0, 4.0 };
    std::cout << point1; // 程序在此处依赖 std::cout
    return 0;
}
在上例中,Point 与 std::ostream 并无直接关联,但因 operator<< 使用 std::ostream 打印 Point,故 Point 对 std::ostream 存在依赖。
依赖与关联在 C++ 中的区别
依赖与关联常被混淆。在 C++ 中:
- 关联是一种关系,其中一个类以数据成员的形式保存对关联类的直接或间接“链接”。例如,Doctor类保存指向其Patient的指针数组;你可以随时询问医生有哪些病人;Driver类保存其拥有的Car的 ID(整数成员),司机始终知道自己关联哪辆车。
- 依赖通常不作为成员存在。被依赖的对象往往是按需临时创建(如打开文件写入数据),或作为函数参数传入(如上述 operator<<中的std::ostream)。
幽默一刻
依赖(感谢 xkcd 的朋友):

当然,我们都知道这其实是一个自反关联!
