Relationships in UML are used to connect UML Classes, and represent various Class Relationships. All UML links can contain:
- Name
- Role labels
- Directionality
- Unidirectional
- Bidirectional
Let’s say we have a
Cube
class, that can move to a 3 dimensional point in space. Instead of representing the location as a 3-tuple ofdouble
, it would be better to create aPoint
class, which the Cube uses to move.
Dependency Relationship
If we have a Dependency class relationship, we use a straight, dotted line. In most cases it is unidirectional, (A depends on B, not vice versa), but there are cases where it is bidirectional (A and B depend on each other)
Example
If the cube doesn’t store the Point
instance anywhere, it only has a dependency on it to move. Specifically, this is a unidirectional dependency on Point
, as Point doesn’t depend on Cube for anything.
classDiagram
direction LR
class Cube{
-position: double[3]
+move(pos: Point)
}
class Point{
+x: double
+y: double
+z: double
}
Cube ..> Point: uses
Association Relationship
An Association relationship is represented as a straight, solid line connecting two UML classes. It can contain text labels, as well as arrowheads if it is unidirectional.
It also contains some additional properties: multiplicity and type. It even supports self-association
Multiplicity
How many objects of the class are related.
Text | UML Representation |
---|---|
One-to-one | A [1] ------- [1] B |
One-to-many | A [1] ------- [*] B |
One-to-(one or more) | A [1] ------- [1..*] B |
One-to-zero or one | A [1] ------- [0..1] B |
One-to-a bounded interval (a to b) | A [1] ------- [a..b] B |
One-to- | A [1] -------- [n] B |
One-to-a set of choices (one-to-five or eight) | A [1] ------- [1, 3, 5..8] B |
Type
- Plain association: Represented with an arrowhead ()#tosee
- Aggregation: Represented with a an open diamond
- Composition: Represented with a filled diamond
Self Association
An class can have instances which are associated with other instances of the same class. This is simply represented as a link to itself.
Example
In Graph (Maths)s, a Node
is associated to other Node
s.
If we have a complete graph with nodes, each node is connected to other nodes.
So we have self-association
classDiagram
direction DU
Graph "1" -- "n" Node
Node -- "n-1" Node: "Connected to"
Aggregation Relationship
Represented with a empty diamond.
Remember that aggregation is a subset of association, so we can also include multiplicity!
Example
A Structure
can be made up of multiple Cube
s. However, these Cube
s can exist independent of the structure, showing an Aggregation relationship between the two.
classDiagram
Structure --o "*" Cube
Composition Relationship
Represented with a black filled diamond
Example
Let’s say Cube
is modified to store a Point
as for it’s position, instead of the double
3-tuple. Here we have an association relationship, more specifically, a Composition relationship, because if we delete the Cube
instance, the Point
instance gets deleted as well!
classDiagram
class Cube{
-position: Point
+setPosition()
}
class Point{
+x: double
+y: double
+z: double
}
Cube ..* Point
If we define the Cube
to contain 8 vertices, which are also Point
s, then we can add multiplicity:
classDiagram
direction LR
class Cube{
-vertices: Point[8]
-position: Point
+setPosition()
}
class Point{
+x: double
+y: double
+z: double
}
Cube ..* "8" Point:
This is read as a Cube
is composed of 8 Point
s
Inheritance Relationship
When a class inherits from another class, we can represent the relationship between the UML classes.
Inheritance relationships are represented with an open arrowhead.
Example
A Character
inherits from a GameObject
. If GameObject
is an Abstract Class, we can italicise it.
Mermaid (the tool I use to draw these diagrams) doesn’t support it, so I use the abstract annotation.
classDiagram
class GameObject
<<abstract>> GameObject
GameObject <|-- Character
Interface Relationship
Represented with a dashed line with an open arrowhead.
Example
A Character
and Projectile
are Moveable
classDiagram
direction BT
class Character{
+move() void
}
class Projectile{
+move() void
}
class Moveable{
<<interface>>
+move() void
}
Character ..|> Moveable
Projectile ..|> Moveable