Mermaid Class Diagrams (UML)
UML class diagrams show the structure of a system by displaying classes, their attributes, methods, and relationships. Essential for documenting object-oriented designs and system architecture.
Use Case
Use class diagrams when you need to:
- Document system architecture
- Show class relationships and hierarchies
- Design object-oriented systems
- Communicate structure to team members
UML Symbol Reference
Class Structure
1βββββββββββββββββββ
2β ClassName β β Class name
3βββββββββββββββββββ€
4β - privateAttr β β Attributes (- private, + public, # protected, ~ package)
5β + publicAttr β
6βββββββββββββββββββ€
7β + method() β β Methods
8β - helper() β
9βββββββββββββββββββ
Relationships
| Symbol | Meaning | Description |
|---|---|---|
<|-- | Inheritance | "extends" or "is-a" relationship |
*-- | Composition | Strong ownership, part cannot exist without whole |
o-- | Aggregation | Weak ownership, part can exist independently |
--> | Association | General relationship |
..|> | Realization | Implements interface |
..> | Dependency | Uses or depends on |
Multiplicity
| Symbol | Meaning |
|---|---|
"1" | Exactly one |
"0..1" | Zero or one |
"1..*" | One or more |
"*" | Zero or more |
"n" | Exactly n |
Code
1```mermaid
2classDiagram
3 class Animal {
4 +String name
5 +int age
6 +makeSound()
7 }
8
9 class Dog {
10 +String breed
11 +bark()
12 }
13
14 Animal <|-- Dog
15```
Result:
Explanation
class ClassName- Define a class+- Public visibility-- Private visibility#- Protected visibility~- Package/Internal visibility<|--- Inheritance arrow*--- Compositiono--- Aggregation
Examples
Example 1: Basic Class Hierarchy
1```mermaid
2classDiagram
3 class Shape {
4 <<abstract>>
5 -String color
6 -int x
7 -int y
8 +draw()*
9 +move(int, int)
10 +getArea()* double
11 }
12
13 class Circle {
14 -double radius
15 +draw()
16 +getArea() double
17 }
18
19 class Rectangle {
20 -double width
21 -double height
22 +draw()
23 +getArea() double
24 }
25
26 Shape <|-- Circle
27 Shape <|-- Rectangle
28```
Result:
Example 2: Relationships and Multiplicity
1```mermaid
2classDiagram
3 class University {
4 +String name
5 +addDepartment()
6 }
7
8 class Department {
9 +String name
10 +addProfessor()
11 }
12
13 class Professor {
14 +String name
15 +teach()
16 }
17
18 class Student {
19 +String name
20 +enroll()
21 }
22
23 class Course {
24 +String title
25 +int credits
26 }
27
28 University "1" *-- "1..*" Department : contains
29 Department "1" o-- "*" Professor : employs
30 Professor "1" --> "*" Course : teaches
31 Student "*" --> "*" Course : enrolls in
32```
Result:
Example 3: Interfaces and Implementation
1```mermaid
2classDiagram
3 class Drawable {
4 <<interface>>
5 +draw()
6 }
7
8 class Serializable {
9 <<interface>>
10 +serialize() String
11 +deserialize(String)
12 }
13
14 class Document {
15 -String content
16 -String author
17 +save()
18 +load()
19 }
20
21 Drawable <|.. Document : implements
22 Serializable <|.. Document : implements
23```
Result:
Example 4: Stereotypes and Annotations
1```mermaid
2classDiagram
3 class DataProcessor {
4 <<service>>
5 +process(data)
6 }
7
8 class DataRepository {
9 <<repository>>
10 +save(entity)
11 +findById(id)
12 }
13
14 class DataEntity {
15 <<entity>>
16 +Long id
17 +String data
18 }
19
20 DataProcessor ..> DataRepository : uses
21 DataRepository --> DataEntity : manages
22```
Result:
Notes
- Use
<<stereotype>>for annotations (abstract, interface, service, etc.) *after method name indicates abstract method- Return types can be specified after method:
getArea() double - Use meaningful relationship labels for clarity
Gotchas/Warnings
- β οΈ Complexity: Large diagrams become hard to read - break into multiple diagrams
- β οΈ Layout: Mermaid auto-layouts - you can't control exact positioning
- β οΈ Generics: Generic types like
List<T>need special handling - β οΈ Bidirectional: Show only one direction for bidirectional relationships
Practical Example: Python E-Commerce System
Python Code
1from abc import ABC, abstractmethod
2from typing import List, Optional
3from datetime import datetime
4
5# Abstract base class (inheritance)
6class PaymentProcessor(ABC):
7 """Abstract payment processor - demonstrates inheritance"""
8
9 @abstractmethod
10 def process_payment(self, amount: float) -> bool:
11 pass
12
13 @abstractmethod
14 def refund(self, transaction_id: str) -> bool:
15 pass
16
17# Concrete implementations
18class StripeProcessor(PaymentProcessor):
19 def __init__(self, api_key: str):
20 self.api_key = api_key
21
22 def process_payment(self, amount: float) -> bool:
23 print(f"Processing ${amount} via Stripe")
24 return True
25
26 def refund(self, transaction_id: str) -> bool:
27 print(f"Refunding transaction {transaction_id}")
28 return True
29
30class PayPalProcessor(PaymentProcessor):
31 def __init__(self, client_id: str, secret: str):
32 self.client_id = client_id
33 self.secret = secret
34
35 def process_payment(self, amount: float) -> bool:
36 print(f"Processing ${amount} via PayPal")
37 return True
38
39 def refund(self, transaction_id: str) -> bool:
40 print(f"Refunding transaction {transaction_id}")
41 return True
42
43# Value object (composition)
44class Address:
45 """Address value object - demonstrates composition"""
46
47 def __init__(self, street: str, city: str, country: str, postal_code: str):
48 self.street = street
49 self.city = city
50 self.country = country
51 self.postal_code = postal_code
52
53 def format(self) -> str:
54 return f"{self.street}, {self.city}, {self.country} {self.postal_code}"
55
56# Entity with composition
57class Customer:
58 """Customer entity - demonstrates composition"""
59
60 def __init__(self, customer_id: str, name: str, email: str, address: Address):
61 self.customer_id = customer_id
62 self.name = name
63 self.email = email
64 self.address = address # Composition: Customer HAS-A Address
65 self.orders: List['Order'] = []
66
67 def add_order(self, order: 'Order'):
68 self.orders.append(order)
69
70# Product entity
71class Product:
72 """Product entity"""
73
74 def __init__(self, product_id: str, name: str, price: float, stock: int):
75 self.product_id = product_id
76 self.name = name
77 self.price = price
78 self.stock = stock
79
80 def reduce_stock(self, quantity: int) -> bool:
81 if self.stock >= quantity:
82 self.stock -= quantity
83 return True
84 return False
85
86# Order item (composition)
87class OrderItem:
88 """Order item - demonstrates composition"""
89
90 def __init__(self, product: Product, quantity: int):
91 self.product = product # Composition
92 self.quantity = quantity
93 self.price_at_purchase = product.price
94
95 def get_total(self) -> float:
96 return self.price_at_purchase * self.quantity
97
98# Main aggregate (dependency injection + composition)
99class Order:
100 """Order aggregate - demonstrates DI and composition"""
101
102 def __init__(self, order_id: str, customer: Customer,
103 payment_processor: PaymentProcessor): # Dependency Injection
104 self.order_id = order_id
105 self.customer = customer # Composition
106 self.items: List[OrderItem] = [] # Composition
107 self.payment_processor = payment_processor # DI (Dependency Inversion)
108 self.status = "pending"
109 self.created_at = datetime.now()
110
111 def add_item(self, product: Product, quantity: int):
112 """Depends on Product (dependency)"""
113 if product.reduce_stock(quantity):
114 item = OrderItem(product, quantity)
115 self.items.append(item)
116
117 def calculate_total(self) -> float:
118 return sum(item.get_total() for item in self.items)
119
120 def checkout(self) -> bool:
121 """Uses injected payment processor (Dependency Inversion)"""
122 total = self.calculate_total()
123 if self.payment_processor.process_payment(total):
124 self.status = "paid"
125 return True
126 return False
127
128# Repository (depends on Order)
129class OrderRepository:
130 """Repository - demonstrates dependency"""
131
132 def __init__(self):
133 self.orders: List[Order] = []
134
135 def save(self, order: Order): # Depends on Order
136 self.orders.append(order)
137
138 def find_by_id(self, order_id: str) -> Optional[Order]:
139 return next((o for o in self.orders if o.order_id == order_id), None)
140
141# Usage example
142if __name__ == "__main__":
143 # Create payment processor (can be swapped - Dependency Inversion)
144 payment = StripeProcessor(api_key="sk_test_123")
145
146 # Create customer with address (Composition)
147 address = Address("123 Main St", "New York", "USA", "10001")
148 customer = Customer("C001", "John Doe", "john@example.com", address)
149
150 # Create products
151 laptop = Product("P001", "Laptop", 999.99, 10)
152 mouse = Product("P002", "Mouse", 29.99, 50)
153
154 # Create order with DI
155 order = Order("O001", customer, payment)
156 order.add_item(laptop, 1)
157 order.add_item(mouse, 2)
158
159 # Process order
160 order.checkout()
161
162 # Save to repository
163 repo = OrderRepository()
164 repo.save(order)
UML Diagram
1```mermaid
2classDiagram
3 %% Abstract base class
4 class PaymentProcessor {
5 <<abstract>>
6 +process_payment(amount) bool*
7 +refund(transaction_id) bool*
8 }
9
10 %% Concrete implementations (Inheritance)
11 class StripeProcessor {
12 -String api_key
13 +process_payment(amount) bool
14 +refund(transaction_id) bool
15 }
16
17 class PayPalProcessor {
18 -String client_id
19 -String secret
20 +process_payment(amount) bool
21 +refund(transaction_id) bool
22 }
23
24 %% Value object
25 class Address {
26 +String street
27 +String city
28 +String country
29 +String postal_code
30 +format() String
31 }
32
33 %% Entities
34 class Customer {
35 +String customer_id
36 +String name
37 +String email
38 +List~Order~ orders
39 +add_order(order)
40 }
41
42 class Product {
43 +String product_id
44 +String name
45 +float price
46 +int stock
47 +reduce_stock(quantity) bool
48 }
49
50 class OrderItem {
51 +int quantity
52 +float price_at_purchase
53 +get_total() float
54 }
55
56 class Order {
57 +String order_id
58 +String status
59 +DateTime created_at
60 +List~OrderItem~ items
61 +add_item(product, quantity)
62 +calculate_total() float
63 +checkout() bool
64 }
65
66 class OrderRepository {
67 -List~Order~ orders
68 +save(order)
69 +find_by_id(order_id) Order
70 }
71
72 %% Inheritance relationships
73 PaymentProcessor <|-- StripeProcessor : extends
74 PaymentProcessor <|-- PayPalProcessor : extends
75
76 %% Composition relationships (strong ownership)
77 Customer *-- Address : has
78 Order *-- OrderItem : contains
79 OrderItem *-- Product : references
80
81 %% Aggregation (weak ownership)
82 Customer o-- Order : places
83
84 %% Dependency Injection (uses interface)
85 Order --> PaymentProcessor : uses (DI)
86
87 %% Dependencies
88 OrderRepository ..> Order : depends on
89 Order ..> Product : depends on
90```
Result:
Relationship Explanations
Inheritance (
<|--):StripeProcessorandPayPalProcessorextendPaymentProcessor- IS-A relationship
- Subclasses inherit abstract methods
Composition (
*--): Strong ownership, lifecycle dependentCustomerhasAddress- address can't exist without customerOrdercontainsOrderItem- items can't exist without orderOrderItemreferencesProduct- captures product state
Aggregation (
o--): Weak ownership, independent lifecycleCustomerplacesOrder- orders can exist independently
Dependency Injection (
-->):OrderusesPaymentProcessorinterface- Dependency Inversion Principle
- Order depends on abstraction, not concrete implementation
- Payment processor can be swapped at runtime
Dependency (
..>): Uses but doesn't ownOrderRepositorydepends onOrder- needs it to functionOrderdepends onProduct- uses it but doesn't own it
This example demonstrates SOLID principles:
- Single Responsibility: Each class has one job
- Open/Closed: Can add new payment processors without modifying Order
- Liskov Substitution: Any PaymentProcessor can be used
- Interface Segregation: PaymentProcessor has focused interface
- Dependency Inversion: Order depends on PaymentProcessor abstraction
Related Snippets
- Architecture Diagrams (C4 Model)
Create system architecture diagrams using C4 model with Mermaid - Chart.js Bar Chart
Create bar charts for data visualization - Graphviz DOT Diagrams
Create complex graph layouts with Graphviz DOT language - KaTeX Math Examples and Tips
Comprehensive guide to KaTeX math notation with examples and tips - Mermaid Arbitrary Graphs
Create arbitrary graphs and networks with Mermaid - Mermaid Block Diagrams
Create block diagrams for system architecture with Mermaid - Mermaid Charts (Pie, Bar, Line)
Create pie charts, bar charts, and line charts with Mermaid - Mermaid Entity Relationship Diagrams
Create Entity Relationship Diagrams (ERD) with Mermaid - Mermaid Flowchart
Create flowcharts and decision trees with Mermaid - Mermaid Gantt Chart
Create Gantt charts for project timelines and scheduling - Mermaid Git Diagrams
Create Git branch and commit diagrams with Mermaid - Mermaid Kanban Boards
Create Kanban boards for project management with Mermaid - Mermaid Mindmaps
Create mindmaps for brainstorming and organizing ideas with Mermaid - Mermaid Packet Diagrams
Create packet diagrams for network protocols with Mermaid - Mermaid Quadrant Charts
Create quadrant charts for prioritization with Mermaid - Mermaid Radar Charts
Create radar charts for multi-dimensional comparisons with Mermaid - Mermaid Requirement Diagrams
Create requirement diagrams for system requirements with Mermaid - Mermaid Sankey Diagrams
Create Sankey diagrams for flow visualization with Mermaid - Mermaid Sequence Diagram
Create sequence diagrams for interactions and API flows - Mermaid State Diagrams
Create state diagrams and state machines with Mermaid - Mermaid Timeline Diagrams
Create timeline diagrams for chronological events with Mermaid - Mermaid Treemap Diagrams
Create treemap diagrams for hierarchical data visualization with Mermaid - Mermaid User Journey Diagrams
Create user journey maps with Mermaid - Mermaid ZenUML Diagrams
Create ZenUML sequence diagrams with Mermaid - P5.js Interactive Visualizations
Create interactive visualizations and animations with P5.js