类图(ClassDiagrams)是系统中类及类间关系的静态描述视图。由多个类及这些类间的关系组成。功能有两种:

  • 显示系统内部信息结构,描述信息行为
  • 为其他图(顺序图、交互图)定义基础

在系统设计阶段,类图直接引导OOP语言实现类。通俗来说就是按照类图来写类,或者换个说法就是类及类间关系设计工作在类图设计阶段就完成。编码实现时只用照着类图来就行。

btw举例中会用PlantUML再实现一次,非常简单。借助plantUML可以大幅度缩减绘图时间

类封装了数据和行为,是面向对象的重要组成部分,它是具有相同属性、操作、关系的对应集合的总称。在设计类的时候,将类的职责分解为类的属性和操作。类的属性即类的数据职责,类的操作即类的行为职责。

类属性及表示方式

在UML类图中,类使用带有分割线的矩形来表示,其中包含类名,属性(field)、和方法(metod)。比如下边的Employee类: 类图 - 图1对应plaintext为:

  1. class Employee {
  2. -name
  3. -age
  4. -email
  5. +modifyinfo()
  6. }

类成员前的符号表示成员属性,+表public,-表peivate,#表protected/friend。所以Employee就有三个私有属性和一个公有方法。
属性的完整表示方式:可见性 名称 :类型 [ = 缺省值]中括号中的内容表示是可选的。
方法的完整表示方式:可见性 名称(参数列表) [ : 返回类型]中括号中的内容是可选的。

类的方法和表示方式

下图的Demo类中有三个方法:

类图 - 图2对应的plaintext为:

  1. @startuml
  2. class Demo{
  3. + method(Object par) :void
  4. # method2() :String
  5. - mothod3(int par1,int par2[]) : int
  6. }
  7. @enduml
  • public方法method1接收一个类型为Object的参数,返回值类型为void
  • protected方法method2无参数,返回值类型为String
  • private方法method3接收类型分别为int、int[]的参数,返回值类型为int

    类间关系的表示方式

    关联关系

    关联关系又可进一步分为单向关联、双向关联和自关联

    单向关联

    我们可以看到,在UML类图中单向关联用一个带箭头的直线表示。上图表示每个顾客都有一个地址,这通过让Customer类持有一个类型为Address的成员变量类实现。 类图 - 图3plaintext: ``` @startuml

class Customer{

  • address: Address }

class Address{

} Customer —> Address

@enduml

  1. <a name="wam2K"></a>
  2. ### 双向关联
  3. 从上图中我们很容易看出,所谓的双向关联就是双方各自持有对方类型的成员变量。在UML类图中,双向关联用一个不带箭头的直线表示。上图中在Customer类中维护一个Product[]数组,表示一个顾客购买了那些产品;在Product类中维护一个Customer类型的成员变量表示这个产品被哪个顾客所购买。
  4. ![](https://cdn.nlark.com/yuque/__puml/cd6061a5fa2ab391c0ad8703d5e1dfcd.svg#lake_card_v2=eyJ0eXBlIjoicHVtbCIsImNvZGUiOiJAc3RhcnR1bWxcblxuY2xhc3MgQ3VzdG9tZXJ7XG4gIC0gcHJvZHVjdHM6UHJvZHVjdFtdXG59XG5cbmNsYXNzIFByb2R1Y3R7XG5cdC0gY3VzdG9tZXI6Q3VzdG9tZXJcbn1cbkN1c3RvbWVyIFwicHVyY2hhc2VcIjwtLT5cImlzIHNvbGQgdG9cIiBQcm9kdWN0XG5AZW5kdW1sIiwidXJsIjoiaHR0cHM6Ly9jZG4ubmxhcmsuY29tL3l1cXVlL19fcHVtbC9jZDYwNjFhNWZhMmFiMzkxYzBhZDg3MDNkNWUxZGZjZC5zdmciLCJpZCI6ImlUUjM3IiwibWFyZ2luIjp7InRvcCI6dHJ1ZSwiYm90dG9tIjp0cnVlfSwiY2FyZCI6ImRpYWdyYW0ifQ==)plaintext:

@startuml

class Customer{

  • products:Product[] }

class Product{

  1. - customer:Customer

} Customer “purchase”<—>”is sold to” Product @enduml

  1. <a name="A2bSI"></a>
  2. ### 自关联
  3. 自关联在UML类图中用一个带有箭头且指向自身的直线表示。上图的意思就是Node类包含类型为Node的成员变量,也就是“自己包含自己”。
  4. ![](https://cdn.nlark.com/yuque/__puml/6bd330464f7222c7025f02701fdf4983.svg#lake_card_v2=eyJ0eXBlIjoicHVtbCIsImNvZGUiOiJAc3RhcnR1bWxcblxuY2xhc3MgTm9kZXtcbiAgLSBzdWJOb2Rl77yaTm9kZVxufVxuXG5Ob2RlIC0tPiBOb2RlIDogY29udGFpbnNcbkBlbmR1bWwiLCJ1cmwiOiJodHRwczovL2Nkbi5ubGFyay5jb20veXVxdWUvX19wdW1sLzZiZDMzMDQ2NGY3MjIyYzcwMjVmMDI3MDFmZGY0OTgzLnN2ZyIsImlkIjoidElpSWkiLCJtYXJnaW4iOnsidG9wIjp0cnVlLCJib3R0b20iOnRydWV9LCJjYXJkIjoiZGlhZ3JhbSJ9)plaintext:

@startuml

class Node{

  • subNode:Node }

Node —> Node : contains @enduml

  1. <a name="xLLb0"></a>
  2. ## 聚合关系
  3. 上图中的Car类与Engine类就是聚合关系(Car类中包含一个Engine类型的成员变量)。由上图我们可以看到,UML中聚合关系用带空心菱形和箭头的直线表示。聚合关系强调是“整体”包含“部分”,但是“部分”可以脱离“整体”而单独存在。比如上图中汽车包含了发动机,而发动机脱离了汽车也能单独存在。
  4. ![](https://cdn.nlark.com/yuque/__puml/f7331ec0afd8ae5b5773efcb506e93e3.svg#lake_card_v2=eyJ0eXBlIjoicHVtbCIsImNvZGUiOiJAc3RhcnR1bWxcblxuY2xhc3MgQ2Fye1xuICAtIGVuZ2luZTogRW5naW5lXG5cdCsgQ2FyKEVuZ2luZSBlbmdpbmUpXG5cdCsgc2V0RW5naW5lKEVuZ2luZSBlbmdpbmUpIDogdm9pZFxufVxuY2xhc3MgRW5naW5le1xufVxuXG5DYXIgby0tIEVuZ2luZSA6IGNvbnRhaW5zXG5AZW5kdW1sIiwidXJsIjoiaHR0cHM6Ly9jZG4ubmxhcmsuY29tL3l1cXVlL19fcHVtbC9mNzMzMWVjMGFmZDhhZTViNTc3M2VmY2I1MDZlOTNlMy5zdmciLCJpZCI6InhNTUdtIiwibWFyZ2luIjp7InRvcCI6dHJ1ZSwiYm90dG9tIjp0cnVlfSwiY2FyZCI6ImRpYWdyYW0ifQ==)plaintext:

@startuml

class Car{

  • engine: Engine
    • Car(Engine engine)
    • setEngine(Engine engine) : void } class Engine{ }

Car o— Engine : contains @enduml

  1. <a name="N2qma"></a>
  2. ## 组合关系
  3. 组合关系与聚合关系见得最大不同在于:这里的“部分”脱离了“整体”便不复存在。比如下图:<br />显然,嘴是头的一部分且不能脱离了头而单独存在。在UML类图中,组合关系用一个带实心菱形和箭头的直线表示。
  4. ![](https://cdn.nlark.com/yuque/__puml/2002d365d6b7e10e4baa203500baacc1.svg#lake_card_v2=eyJ0eXBlIjoicHVtbCIsImNvZGUiOiJAc3RhcnR1bWxcblxuY2xhc3MgSGVhZHtcblx0LSBtb3VudGg6IE1vdXRoXG5cdCsgSGVhZCgpXG59XG5jbGFzcyBNb3V0aHtcbn1cblxuSGVhZCAqLS0gTW91dGggOiBoYXNcbkBlbmR1bWwiLCJ1cmwiOiJodHRwczovL2Nkbi5ubGFyay5jb20veXVxdWUvX19wdW1sLzIwMDJkMzY1ZDZiN2UxMGU0YmFhMjAzNTAwYmFhY2MxLnN2ZyIsImlkIjoiQlNjblIiLCJtYXJnaW4iOnsidG9wIjp0cnVlLCJib3R0b20iOnRydWV9LCJjYXJkIjoiZGlhZ3JhbSJ9)plaintext:

@startuml

class Head{

  1. - mounth: Mouth
  2. + Head()

} class Mouth{ }

Head *— Mouth : has @enduml

  1. <a name="y0nUQ"></a>
  2. ## 依赖关系
  3. 从上图我们可以看到,Driver的drive方法只有传入了一个Car对象才能发挥作用,因此我们说Driver类依赖于Car类。在UML类图中,依赖关系用一条带有箭头的虚线表示。
  4. ![](https://cdn.nlark.com/yuque/__puml/dc7680280b12b969c09c1b7b80042f5e.svg#lake_card_v2=eyJ0eXBlIjoicHVtbCIsImNvZGUiOiJAc3RhcnR1bWwgXG5jbGFzcyBEcml2ZXJ7XG5cdCsgZHJpdmUoQ2FyIGNhcilcdDogdm9pZFxufVxuY2xhc3MgQ2Fye1xuXHQrIG1vdmUoKVx0OnZvaWRcdFxufVxuQ2FyIDwuLiBEcml2ZXJcbkBlbmR1bWwiLCJ1cmwiOiJodHRwczovL2Nkbi5ubGFyay5jb20veXVxdWUvX19wdW1sL2RjNzY4MDI4MGIxMmI5NjljMDljMWI3YjgwMDQyZjVlLnN2ZyIsImlkIjoiQWVEMG8iLCJtYXJnaW4iOnsidG9wIjp0cnVlLCJib3R0b20iOnRydWV9LCJjYXJkIjoiZGlhZ3JhbSJ9)plaintext:

@startuml class Driver{

  1. + drive(Car car) : void

} class Car{

  1. + move() :void

} Car <.. Driver @enduml

  1. <a name="OhdTm"></a>
  2. ## 继承关系
  3. 继承关系对应的是extend关键字,在UML类图中用带空心三角形的直线表示,如下图所示中,Student类与Teacher类继承了Person类。
  4. ![](https://cdn.nlark.com/yuque/__puml/3ccefc09dafa489c25dd600c3296f547.svg#lake_card_v2=eyJ0eXBlIjoicHVtbCIsImNvZGUiOiJAc3RhcnR1bWxcbmNsYXNzIFBlcnNvbntcblx0IyBuYW1lXHQ6U3RyaW5nXG5cdCMgYWdlXHRcdDppbnRcblx0KyBtb3ZlKCk6dm9pZFxuXHQrIHNheSgpIDp2b2lkXG59XG5jbGFzcyBTdHVkZW50e1xuXHQtIHN0dWRlbnROb1x0OlN0cmluZ1xuXHQrIHN0dWR5KClcdFx0OnZvaWRcbn1cbmNsYXNzIFRlYWNoZXJ7XG5cdC0gdGVhY2hlck5vXHQ6U3RyaW5nXG5cdCsgdGVhY2goKVx0XHQ6dm9pZFxufVxuUGVyc29uIDx8LS0gU3R1ZGVudFxuUGVyc29uIDx8LS0gVGVhY2hlclxuQGVuZHVtbCIsInVybCI6Imh0dHBzOi8vY2RuLm5sYXJrLmNvbS95dXF1ZS9fX3B1bWwvM2NjZWZjMDlkYWZhNDg5YzI1ZGQ2MDBjMzI5NmY1NDcuc3ZnIiwiaWQiOiJ1Z3Y3bSIsIm1hcmdpbiI6eyJ0b3AiOnRydWUsImJvdHRvbSI6dHJ1ZX0sImNhcmQiOiJkaWFncmFtIn0=)plaintext:

@startuml class Person{

  1. # name :String
  2. # age :int
  3. + move():void
  4. + say() :void

} class Student{

  1. - studentNo :String
  2. + study() :void

} class Teacher{

  1. - teacherNo :String
  2. + teach() :void

} Person <|— Student Person <|— Teacher @enduml

  1. <a name="XNh7Y"></a>
  2. ## 接口实现关系
  3. 这种关系对应implement关键字,在UML类图中用带空心三角形的虚线表示。如下图中,Car类与Ship类都实现了Vehicle接口。下图中car和ship都是Vegicle的实现
  4. ![](https://cdn.nlark.com/yuque/__puml/18b4f73825d5c31726301fd05d99afad.svg#lake_card_v2=eyJ0eXBlIjoicHVtbCIsImNvZGUiOiJAc3RhcnR1bWxcbmNsYXNzIFZlaGljbGV7XG5cdFx0KyBtb3ZlKClcdDp2b2lkXG59XG5jbGFzcyBTaGlwe1xuXHRcdCsgbW92ZSgpXHQ6dm9pZFx0XG59XG5jbGFzcyBDYXJ7XG5cdFx0KyBtb3ZlKClcdDp2b2lkXG59XG5WZWhpY2xlIDx8Li4gU2hpcFxuVmVoaWNsZSA8fC4uIENhclxuQGVuZHVtbCIsInVybCI6Imh0dHBzOi8vY2RuLm5sYXJrLmNvbS95dXF1ZS9fX3B1bWwvMThiNGY3MzgyNWQ1YzMxNzI2MzAxZmQwNWQ5OWFmYWQuc3ZnIiwiaWQiOiJvR1VUciIsIm1hcmdpbiI6eyJ0b3AiOnRydWUsImJvdHRvbSI6dHJ1ZX0sImNhcmQiOiJkaWFncmFtIn0=)plaintext

@startuml class Vehicle{

  1. + move() :void

} class Ship{

  1. + move() :void

} class Car{

  1. + move() :void

} Vehicle <|.. Ship Vehicle <|.. Car @enduml ```

参考文章