开始这堂关于类图 (Class Diagram) 的课程。这是一种在软件设计阶段非常有用的图表,尤其是在进行面向对象编程 (OOP) 时。

如果说流程图是描述动作的“剧本”,时序图是描述对话的“分镜”,那么类图就是描绘所有角色(对象)内在结构和相互关系的“人物设定图”。它是一张静态的、展示系统结构的蓝图。

本课程的所有示例都将以 Bash Shell 为标准。

第二部分:常用图表绘制

第6章:类图 (Class Diagram) - 软件设计

6.1 类图声明与类的定义 (classDiagram, class)

6.1.1 classDiagram 关键字

第一步:声明图表类型

与我们之前学过的图表一样,任何一个类图都必须classDiagram 这个关键字开头。这行代码告诉Mermaid渲染引擎:“我接下来要画的是一个类图”。

我们先写下这最基本的第一行:

代码段

classDiagram

这行代码会创建一个空白的类图画布。

6.1.2 class 关键字

第二步:明确地定义一个类

使用 class 关键字,可以显式地声明一个类。这会在图表上创建一个带有类名的方框。

我们来定义一个 Animal 类:

代码段

classDiagram
  class Animal

这会生成一个简单的、名为 Animal 的矩形框。

第三步:隐式地定义类

Mermaid非常智能,如果你直接描述类之间的关系,它会自动为你创建不存在的类。

代码段

classDiagram
  Dog --|> Animal # 定义一条从Dog到Animal的继承关系

即使我们没有用 class 关键字,Mermaid也会自动创建出 DogAnimal 两个类,并画出它们之间的关系。不过,明确地使用 class 关键字来定义,通常会让你的图表代码更清晰


6.2 定义类的成员

一个类(方框)通常被分为三个区域:顶部是类名,中间是属性,底部是方法

6.2.1 属性 (Attributes)

第一步:理解属性

属性代表了一个类的数据状态,也就是你在Java等语言中定义的成员变量 (Fields)

第二步:添加属性

我们为一个 Student 类添加 nameage 属性。 语法:在类定义的花括号 {} 内部,直接写下属性名。

代码段

classDiagram
  class Student {
    name
    age
  }

第三步:为属性添加数据类型

为了让设计更清晰,我们应该标明每个属性的数据类型。 语法数据类型 属性名

代码段

classDiagram
  class Student {
    String name
    int age
  }

6.2.2 方法 (Methods)

第一步:理解方法

方法代表了一个类可以执行的行为操作

第二步:添加方法

我们为 Student 类添加 study() 方法。 语法:在属性下方,写下方法名并带上圆括号 ()

代码段

classDiagram
  class Student {
    String name
    int age
    study()
  }

第三步:为方法添加参数和返回类型

一个完整的方法定义应该包含参数和返回类型。 语法返回类型 方法名(参数类型 参数名)

代码段

classDiagram
  class Student {
    String name
    int age
    void study(String course)
    int getAge()
  }

6.2.3 定义可见性 (+ public, - private, # protected, ~ package/internal)

第一步:理解可见性

可见性修饰符(也叫访问修饰符)用来控制一个类的成员(属性或方法)能否被其他类访问,这是封装思想的体现。

第二步:学习符号

  • + : public (公有的),任何类都可以访问。

  • - : private (私有的),只有该类自己内部可以访问。

  • # : protected (受保护的),该类及其子类可以访问。

  • ~ : package (包私有的),同一个包内的类可以访问。

第三步:为成员添加可见性

在成员名前面加上对应的符号即可。

代码段

classDiagram
  class Student {
    -String name
    -int age
    +int getAge()
    +void study(String course)
  }

这个定义表示 nameage 是私有属性,而 getAge()study() 是公开的方法,这是一种非常标准的封装实践。

6.2.4 定义静态成员 ($)

第一步:理解静态成员

静态成员(用 static 关键字修饰)属于整个类,而不是某个具体的对象实例。

第二步:学习符号

在成员名后加上美元符号 $,表示它是静态的。

第三步:添加静态成员

我们为 Student 类添加一个静态属性 studentCount 来记录学生总数。

代码段

classDiagram
  class Student {
    -String name
    +int studentCount$
    +int getStudentCount()$
  }

在标准的UML图中,静态成员下方会有一条下划线,Mermaid通过 $ 符号来表示这个概念。


6.3 定义类之间的关系

这是类图最强大的地方,它能清晰地展示出系统内各个模块是如何相互关联的。

6.3.1 继承 (<|--)

  • 含义: 表示一种 "is-a" (是一个)的关系。子类继承父类的所有公共和受保护成员。

  • 语法: 子类 <|-- 父类 (一个空心三角箭头指向父类)

  • 示例: “狗”是一个“动物”。

    代码段

    classDiagram
      class Animal
      class Dog
      Dog <|-- Animal
    

6.3.2 实现 (<|..)

  • 含义: 表示一个类实现了一个接口

  • 语法: 实现类 <|.. 接口 (一条虚线和一个空心三角箭头指向接口)

  • 示例: “鸟”实现了“能飞”这个接口。

    代码段

    classDiagram
      class Flyable {
        <<interface>>
      }
      class Bird
      Bird <|.. Flyable
    

6.3.3 组合 (*--)

  • 含义: 一种强烈的 "has-a" (有一个)或“部分-整体”的关系,部分与整体生命周期相同。如果整体被销毁,部分也随之销毁。

  • 语法: 整体 *-- 部分 (一个实心菱形箭头指向整体)

  • 示例: “房子”由“房间”组成。房子没了,房间自然也没了。

    代码段

    classDiagram
      class House
      class Room
      House *-- Room
    

6.3.4 聚合 (o--)

  • 含义: 一种较弱的 "has-a" 关系,部分可以独立于整体存在。

  • 语法: 整体 o-- 部分 (一个空心菱形箭头指向整体)

  • 示例: “班级”里有“学生”。班级解散了,学生依然存在,可以加入别的班级。

    代码段

    classDiagram
      class Class
      class Student
      Class o-- Student
    

6.3.5 关联 (--)

  • 含义: 表示类之间有一种比较平等的、结构化的联系,但生命周期互相独立。

  • 语法: ClassA -- ClassB (一条实线)

  • 示例: “学生”和“老师”之间存在关联。

    代码段

    classDiagram
      class Student
      class Teacher
      Student -- Teacher
    

6.3.6 依赖 (..>)

  • 含义: 一种非常弱的**“uses-a”**(使用一个)关系。一个类的某个方法使用了另一个类(比如作为方法参数),但并没有把它作为自己的成员变量。

  • 语法: 使用者 ..> 被使用者 (一条虚线和一个普通箭头)

  • 示例: “司机”开车。“司机”这个类的方法里用到了“车”这个对象,但他本身不拥有这辆车。

    代码段

    classDiagram
      class Driver
      class Car
      Driver ..> Car
    

6.4 设置关系的基数(Cardinality / Multiplicity)

第一步:理解基数

基数(也叫多重性)用来精确地表示一个类的多少个实例与另一个类的多少个实例相关联。

第二步:学习基数语法

将基数写在关系线的两端,并用双引号 "" 包裹起来。

第三步:认识常用基数符号

  • "1": 一个

  • "0..1": 零个或一个

  • "*": 零个或多个

  • "1..*": 一个或多个

第四步:为关系添加基数

我们来描述一个订单系统的关系。

代码段

classDiagram
  Customer "1" -- "0..*" Order : places
  Order "1" -- "1..*" OrderLine : contains
  Product "1" -- "*" OrderLine : ordered in
  • 解读:

    • 一个 Customer (顾客) 可以下 0 到多个 Order (订单)。

    • 一个 Order 必须包含 1 到多个 OrderLine (订单项)。

    • 一个 Product (商品) 可以出现在 0 到多个 OrderLine 中。

  • places, contains, ordered in 是关系的可选标签,写在冒号后面。


6.5 添加注解与标签

注解(也叫“构造型”或“版型”,Stereotype)是放在类名上方,用 <<...>> 包裹的文本,用于表示该类的特殊角色。

6.5.1 <<interface>>

第一步:用它来明确表示一个定义是接口

代码段

classDiagram
  class Animal {
    <<interface>>
    +void makeSound()
  }

这会使 Animal 的渲染样式与普通类有所区别。

6.5.2 <<abstract>>

第一步:用它来表示一个类是抽象类

代码段

classDiagram
  class Shape {
    <<abstract>>
    -String color
    +String getColor()
    +double getArea()*
  }
  • 注意:在Mermaid中,抽象方法通常在方法名后加 * 来表示。

6.5.3 <<service>>

第一步:用它来表示一个类是服务类,这在分层架构(如Spring)中很常见。

代码段

classDiagram
  class UserService {
    <<service>>
    +User findUserById(long id)
  }

6.5.4 <<enum>>

第一步:用它来表示一个定义是枚举 (enum)

代码段

classDiagram
  class OrderStatus {
    <<enum>>
    PENDING
    PROCESSING
    COMPLETED
    CANCELLED
  }

个人资料照片

Deep Research

视频

🍌 图片

Canvas

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐