BLOG

Record, summarize, and improve.

UML

对应UML类图:

Image in a image block
  • 类名:粗体,如果是类是抽象类则类名显示为斜体!
  • 属性:
可见性 名称:类型[=默认值]

可见性一般为public、private和protected,在类图分别用+、-和#表示,在Swift中没有与protected完全对应的可见控制,因此选用的是internal对应为#;名称为属性的名称;类型为数据类型;默认值如变量 age默认值为0。

  • 方法:
可见性 名称(参数列表 参数1,参数2) :返回类型

可见性如上名称表达式的介绍,名称就是方法名,参数列表是可选的项,多参数的话参数直接用英文逗号隔开;返回值也是个可选项,返回值类型可以说基本的数据类型、用户自定义类型和void。如果是构造方法,则无返回类型!

类图中类与类之间的关系主要由:继承、实现、依赖、关联、聚合、组合这六大类型。表示方式如下图:

Image in a image block

依赖

  • 依赖表示一个类依赖于另一个类,即一个类通过某种方式使用到另一个类。这种关系是临时的或弱依赖的。
  • 依赖关系通常意味着“使用关系”,类 A 使用了类 B 的某些功能。

A → B(A 依赖于 B),实现方式:函数参数、局部变量、静态函数调用等

class B {};

class A {
public:
    void use(B& b) {
        // A 使用了 B
    }
};

关联

  • 关联表示两个类之间有某种关系,通常是一个类“拥有”另一个类的对象。
  • 可以是单向或双向关联。

实线箭头 表示,箭头指向被关联的一方,双向关联时没有箭头。实现方式:成员变量表示长期持有关系。

class B {};

class A {
private:
    B* b; // A 和 B 关联
};

聚合

  • 聚合是一种特殊的关联关系,表示整体和部分的关系,但部分可以独立于整体存在。
  • “has-a” 的关系,整体和部分生命周期不同。

空心菱形 + 实线箭头 表示,菱形指向整体,箭头指向部分。实现方式:一个类通过指针或引用持有另一个类的对象。

class Engine {};

class Car {
private:
    Engine* engine; // Car 聚合了 Engine
};

组合

  • 组合是一种强聚合关系,表示整体和部分不可分割,部分不能独立存在。
  • “contains-a” 的关系,整体销毁时部分也会销毁。

实心菱形 + 实线箭头 表示,菱形指向整体,箭头指向部分。实现方式:成员变量表示生命周期绑定关系。

class Engine {};

class Car {
private:
    Engine engine; // Car 组合了 Engine
};

继承

  • 继承表示一个类是另一个类的子类(派生类),是一种“is-a”关系。
  • 子类继承父类的所有公开和保护成员。

实线空心三角箭头 表示,箭头从子类指向父类。实现方式:C++ 中使用类的继承

class Parent {};

class Child : public Parent {}; // Child 继承了 Parent

实现

  • 实现表示类实现一个接口,是继承关系的特殊形式。
  • 子类需要实现接口中定义的所有纯虚函数。

虚线空心三角箭头 表示,箭头从实现类指向接口。实现方式:C++ 中使用抽象类或纯虚函数。

class Interface {
public:
    virtual void func() = 0; // 纯虚函数
};

class Implementation : public Interface {
public:
    void func() override {
        // 实现接口方法
    }
};

1. 依赖(Dependency)

  • 定义:方法依赖另一个类的对象,但不长期持有其引用。
  • 示例:打印机依赖文档 Document,但 Printer 不会存储 Document
class Document {
public:
    void showContent() { std::cout << "This is a document." << std::endl; }
};

class Printer {
public:
    void print(Document& doc) {  // 依赖关系:方法参数依赖 Document
        doc.showContent();
    }
};

int main() {
    Document doc;
    Printer printer;
    printer.print(doc);  // 依赖 Document 进行打印
}

🔹 特点Printer 只在 print() 方法调用时使用 Document,不会持有它的引用。


2. 关联(Association)

  • 定义:一个类知道另一个类的存在,但不拥有它的生命周期。
  • 示例:学生(Student)知道老师(Teacher),但 Teacher 不是 Student 的一部分。
class Teacher {
public:
    void teach() { std::cout << "Teaching..." << std::endl; }
};

class Student {
private:
    Teacher* teacher;  // 关联关系:Student 只是持有 Teacher 的指针
public:
    void setTeacher(Teacher* t) { teacher = t; }
    void study() { teacher->teach(); }
};

int main() {
    Teacher t;
    Student s;
    s.setTeacher(&t);  // 关联 Student 和 Teacher
    s.study();
}

🔹 特点Student 仅持有 Teacher 指针,不管理 Teacher 的生命周期。


3. 聚合(Aggregation)

  • 定义:一个类包含另一个类的引用,但不控制其生命周期。
  • 示例:学校(School)包含老师(Teacher),但 Teacher 依然可以独立存在。
#include <vector>

class Teacher {
public:
    void teach() { std::cout << "Teacher is teaching." << std::endl; }
};

class School {
private:
    std::vector<Teacher*> teachers;  // 聚合关系
public:
    void addTeacher(Teacher* t) { teachers.push_back(t); }
    void startClasses() {
        for (auto t : teachers) {
            t->teach();
        }
    }
};

int main() {
    Teacher t1, t2;
    School school;
    school.addTeacher(&t1);
    school.addTeacher(&t2);
    school.startClasses();
}

🔹 特点School 不会销毁 TeacherTeacher 仍然可以独立存在。


4. 组合(Composition)

  • 定义:一个类是另一个类的组成部分,整体对象销毁时,部分对象也会销毁。
  • 示例:人(Person)包含心脏(Heart),Heart 不能脱离 Person 独立存在。
class Heart {
public:
    void beat() { std::cout << "Heart is beating..." << std::endl; }
};

class Person {
private:
    Heart heart;  // 组合关系:Heart 由 Person 拥有
public:
    void live() { heart.beat(); }
};

int main() {
    Person p;
    p.live();  // 心脏随人一起存在
}

🔹 特点Heart 依赖 Person 的生命周期,Person 销毁后Heart 也随之销毁。


5. 继承(Inheritance)

  • 定义:子类继承父类的属性和行为,是 "is-a" 关系
  • 示例:汽车(Car)继承交通工具(Vehicle)。
class Vehicle {
public:
    void move() { std::cout << "Vehicle is moving..." << std::endl; }
};

class Car : public Vehicle {
public:
    void honk() { std::cout << "Car is honking!" << std::endl; }
};

int main() {
    Car myCar;
    myCar.move();  // 继承自 Vehicle
    myCar.honk();  // Car 自己的方法
}

🔹 特点CarVehicle 的特殊类型,可以继承 Vehicle 的方法。


6. 实现(Realization)

  • 定义:类实现了一个接口(抽象类),但 不继承具体实现
  • 示例:鸟(Bird)实现飞行接口(Flyable)。
class Flyable {
public:
    virtual void fly() = 0;  // 纯虚函数
};

class Bird : public Flyable {
public:
    void fly() override { std::cout << "Bird is flying!" << std::endl; }
};

int main() {
    Bird b;
    b.fly();
}

🔹 特点Bird 必须实现 Flyablefly() 方法,否则会编译错误。


总结:六种类关系对比

关系类型 关键字 强度 生命周期 例子
依赖(Dependency) 方法参数 无影响 Printer 依赖 Document
关联(Association) 指针/引用 无影响 Student 关联 Teacher
聚合(Aggregation) std::vector<T*> 较强 整体销毁不影响部分 School 聚合 Teacher
组合(Composition) 成员变量 整体销毁部分也销毁 Person 组合 Heart
继承(Inheritance) class A : public B 受父类影响 Car 继承 Vehicle
实现(Realization) class A : public Interface 受接口影响 Bird 实现 Flyable

选择建议:

  • 仅方法中使用另一个类(短期关系) ➝ 依赖
  • 只需要知道另一个类存在(长期关系) ➝ 关联
  • 一个类包含多个对象,但不控制它们的生命周期 ➝ 聚合
  • 组成关系(生命周期完全依赖整体) ➝ 组合
  • 子类继承父类行为 ➝ 继承
  • 类实现接口,提供特定功能 ➝ 实现

类图详解
顺序图详解
协作图详解
状态图详解
活动图详解
构件图详解
部署图详解