de_DEen_USes_ESfa_IRfr_FRhi_INid_IDpl_PLpt_PTru_RUvizh_CN

Giới thiệu

Biểu đồ Lớp của Ngôn ngữ Mô hình hóa Thống nhất (UML) đóng vai trò như bản thiết kế cho kiến trúc phần mềm, cầu nối giữa các yêu cầu trừu tượng và việc triển khai mã nguồn cụ thể. Bằng cách trực quan hóa cấu trúc của một hệ thống—các lớp, thuộc tính, hoạt động và mối quan hệ giữa chúng—các nhà phát triển có thể đảm bảo thiết kế vững chắc trước khi viết một dòng mã nào.

Hướng dẫn này phân tích cú pháp cốt lõi của Biểu đồ Lớp UML thông qua một bảng tóm tắt toàn diện và áp dụng các khái niệm này vào một tình huống thực tế: Nền tảng Giao đồ Ăn Thống nhất. Đến cuối bài viết này, bạn sẽ hiểu cách mô hình hóa các hệ thống phức tạp liên quan đến kế thừa, giao diện, tổ hợp và tập hợp.


Bảng tóm tắt nhanh Biểu đồ Lớp UML

Phần 1: Các Khối Xây dựng (Cú pháp & Bảng chú giải)

Trước khi đi sâu vào nghiên cứu tình huống, chúng ta cần xác định từ vựng được sử dụng trong các biểu đồ UML.

1. Cấu trúc Lớp & Độ hiển thị

Một lớp được biểu diễn bằng một hình chữ nhật được chia thành ba phần:

  • Phần trên: Tên Lớp (ví dụ: FlightBooking).

  • Phần giữa: Thuộc tính/Tính chất (ví dụ: + nameProperty: String).

  • Phần dưới: Phương thức/Hoạt động (ví dụ: + isActive(): boolean).

Các bộ sửa đổi độ hiển thị:

  • + Công khai: Có thể truy cập bởi bất kỳ lớp nào khác.

  • - Riêng tư: Chỉ có thể truy cập bên trong lớp đó.

  • # Được bảo vệ: Có thể truy cập trong lớp và các lớp con của nó.

  • ~ Gói: Chỉ có thể truy cập trong cùng một gói.

2. Các loại lớp đặc biệt

  • Giao diện (<<interface>>): Hợp đồng xác định các phương thức mà không có phần thực thi. Được biểu diễn bằng hộp màu xanh lá cây (trong bảng tóm tắt này) hoặc ký hiệu chuẩn.

    • Ví dụ: UserRepo với + method(): void.

  • Lớp trừu tượng (<<abstract>>): Lớp cơ sở không thể được khởi tạo trực tiếp. Chúng có thể chứa các phương thức trừu tượng.

    • Ví dụ: Component với + render(): void // abstract.

  • Kiểu liệt kê: Một tập hợp các hằng số có tên.

    • Ví dụ: JobStatus.

Ví dụ về sơ đồ lớp của hệ thống đơn hàng

 

@startuml
skinparam classAttributeIconSize 0
skinparam shadowing false

‘ — CÁC GIA DIỆN —
interface PaymentGateway {
+ process(amount: double): boolean
}

‘ — CÁC LỚP TRỪU TƯỢNG —
abstract class Order {
# orderId: String
# totalAmount: double
+ {abstract} calculateTax(): double
+ getSummary(): String
}

‘ — CÁC LỚP —
class PhysicalOrder {
– shippingWeight: double
+ calculateTax(): double
}

class DigitalOrder {
– downloadLink: String
+ calculateTax(): double
}

class OrderItem {
– productName: String
– price: double
– quantity: int
}

class PayPalGateway {
+ process(amount: double): boolean
}

‘ — MỐI QUAN HỆ —’
Order <|– PhysicalOrder
Order <|– DigitalOrder

Order *– “1..*” OrderItem : chứa
Order ..> PaymentGateway : sử dụng

PaymentGateway <|.. PayPalGateway

@enduml


Phần 2: Mối quan hệ & Số lượng

Các đường nối giữa các lớp xác định cách chúng tương tác.

1. Các loại liên kết

  • Kế thừa (Tổng quát hóa): Đường liền với tam giác rỗng. Mối quan hệ “là một”.

    • Ví dụ: Xe hơi và Xe máy kế thừa từ Phương tiện.

  • Triển khai: Đường đứt nét với tam giác rỗng. Một lớp thực hiện hợp đồng giao diện.

    • Ví dụ: Xe hơi thực hiện Có thể lái.

  • Tổng hợp (Sở hữu mạnh): Đường liền với một hình thoi đầy. “Bộ phận” không thể tồn tại nếu không có “toàn thể.”

    • Ví dụ: Nhà hàng (Toàn thể) sở hữu Thực đơn (Bộ phận). Nếu nhà hàng đóng cửa, thực đơn sẽ biến mất.

  • Tích hợp: Đường liền với một hình thoi rỗng. Mối quan hệ “có-a” trong đó các bộ phận có thể tồn tại độc lập.

    • Ví dụ: Đơn hàng tích hợp Nhà hàng (Nhà hàng vẫn tồn tại ngay cả khi đơn hàng bị xóa).

2. Chú giải về tính đa bội

Các số ở đầu các đường chỉ ra tính đa bội:

  • 1: Chính xác một.

  • 0..1: Không hoặc một (Tùy chọn).

  • 1..*: Một hoặc nhiều (Danh sách bắt buộc).

  • *: Nhiều (Không hoặc nhiều).

Các khái niệm về thừa kế, thực hiện, cấu thành và tích hợp – Ví dụ

@startuml
‘ Các giao diện và lớp cơ sở
interface Drivable {
+ drive()
}
lớp trừu tượng Vehicle {
+ startEngine()
}
‘ Các lớp
class Car {
}
class Motorcycle {
}
class Restaurant {
– name: String
}
class Menu {
}
class Order {
}
‘ Các mối quan hệ
‘ 1. Kế thừa (Tổng quát hóa)
Vehicle <|– Car
Vehicle <|– Motorcycle
‘ 2. Thực hiện
Drivable <|.. Car
‘ 3. Tổ hợp (Sở hữu mạnh)
Restaurant *– Menu : sở hữu
‘ 4. Tập hợp
Order o– Restaurant : liên quan
‘ Ví dụ về số lượng
‘ Nhà hàng có một hoặc nhiều thực đơn (1..*)
‘ Đơn hàng liên quan đến không hoặc một nhà hàng (0..1)
Restaurant “1” *– “1..*” Menu
Đơn hàng “1” o– “0..1” Nhà hàng
@enduml

Phần 3: Nghiên cứu tình huống thực tế: Nền tảng giao đồ ăn thống nhất

Phần này phân tích sơ đồ trung tâm từ bảng tóm tắt, phân tích kiến trúc của một ứng dụng giao đồ ăn.

1. Phân cấp người dùng (Kế thừa & Tổ hợp)

Hệ thống bắt đầu với một lớp chung Người dùng lớp, được đánh dấu là Trừu tượng. Điều này đảm bảo không có đối tượng “Người dùng” chung nào được tạo ra, chỉ có các loại cụ thể.

  • Kế thừa: Khách hàng và Tài xế kế thừa Người dùng.

  • Tổ hợp:

    • Khách hàng có một Địa chỉ giao hàng (Sở hữu mạnh).

    • Tài xế có Thông tin phương tiện (Sở hữu mạnh).

2. Hệ sinh thái Nhà hàng & Thực đơn

Phần này minh họa sự lồng ghép sâu và các bộ sưu tập.

  • Triển khai giao diện: Nhà hàng thực hiện <<giao diện>> Có thể định vị, đảm bảo mỗi nhà hàng đều có dữ liệu vị trí.

  • Chuỗi thành phần:

    • Nhà hàng (1) sở hữu mạnh mẽ Thực đơn (1).

    • Thực đơn chứa Danh mục thực đơn (1..*).

    • Danh mục thực đơn chứa Món ăn trong thực đơn (*).

    • Lưu ý: Cấu trúc này đảm bảo rằng một món ăn trong thực đơn không thể tồn tại nếu không có danh mục, và danh mục không thể tồn tại nếu không có thực đơn.

3. Xử lý đơn hàng và thanh toán

  • Cấu trúc đơn hàng:

    • Đơn hàng có mối quan hệ với Nhà hàng (Tổng hợp).

    • Đơn hàng sở hữu mạnh mẽ Dòng đơn hàng (1..*).

    • Đơn hàng có một Thanh toán (0..1), cho biết thanh toán là tùy chọn trong giai đoạn tạo ban đầu.

  • Chiến lược Thanh toán (Đa hình):

    • Hệ thống sử dụng một giao diện <<interface>> PaymentProcessor.

    • Các lớp cụ thể StripeProcessor và PayPalProcessor thực hiện giao diện này. Điều này cho phép hệ thống chuyển đổi cổng thanh toán mà không cần thay đổi phần cốt lõi Đơn hàng logic.

4. Lớp trừu tượng so với Giao diện (Ví dụ về Phương tiện)

Phần góc trên bên phải của bảng tóm tắt làm rõ một sự nhầm lẫn phổ biến:

  • Lớp trừu tượng (Phương tiện): Ô tô và Xe máy thừa kế từ Phương tiện. Điều này ngụ ý rằng chúng chia sẻ dữ liệu/cấu trúc cốt lõi (ví dụ: loại động cơ, bánh xe).

  • Giao diện (Có thể lái): Xe hơi thực hiện Giao diện Có thể điều khiển được. Điều này ngụ ý rằng Xe hơi có hành vi cụ thể (drive()) mà Xe máy có thể không có (hoặc có thể thực hiện khác).


Phần 4: Trực quan hóa bằng PlantUML

Dưới đây là mã PlantUML để tạo cấu trúc cốt lõi của ‘Nền tảng Giao đồ ăn Thống nhất’ được mô tả trong nghiên cứu tình huống. Bạn có thể sao chép mã này vào bất kỳ trình chỉnh sửa PlantUML nào để xem biểu đồ.

@startuml
' Skinparams cho việc định dạng để phù hợp với phong cách bảng tóm tắt
skinparam classAttributeIconSize 0
skinparam linetype ortho
skinparam shadowing false

' --- CHÚ THÍCH / CÁC KIỂU DẠNG ---
interface "Drivable" as Drivable {
  + drive(): void
}

interface "Locatable" as Locatable {
  + getCoordinates(): Coordinate
}

interface "PaymentProcessor" as PaymentProcessor {
  + process(amount: double): boolean
}

abstract class "User" as User {
  # id: int
  # name: String
  # email: String
  + login(): void
}

abstract class "Vehicle" as Vehicle {
  # model: String
  # year: int
}

class "Car" as Car
class "Motorcycle" as Motorcycle
class "Customer" as Customer
class "Driver" as Driver
class "Restaurant" as Restaurant
class "Menu" as Menu
class "MenuCategory" as MenuCategory
class "MenuItem" as MenuItem
class "Order" as Order
class "OrderLineItem" as OrderLineItem
class "Payment" as Payment
class "StripeProcessor" as StripeProcessor
class "PayPalProcessor" as PayPalProcessor

' --- CÁC MỐI QUAN HỆ ---

' Phân cấp Phương tiện
Vehicle <|-- Car
Vehicle <|-- Motorcycle
Car ..|> Drivable : Thực hiện

' Phân cấp Người dùng
User <|-- Customer
User <|-- Driver

' Các thành phần của Khách hàng/Tài xế
Customer *-- "1" ShippingAddress : Sở hữu mạnh
Driver *-- "1" VehicleDetails : Sở hữu mạnh

' Hệ sinh thái Nhà hàng
Restaurant ..|> Locatable : Thực hiện
Restaurant "1" *-- "1" Menu : Thành phần
Menu "1" *-- "1..*" MenuCategory : Bộ sưu tập
MenuCategory "1" *-- "*" MenuItem : Bộ sưu tập

' Hệ sinh thái Đơn hàng
Order "1" o-- "1" Restaurant : Tập hợp
Order "1" *-- "*" OrderLineItem : Thành phần
Order "1" --> "0..1" Payment

' Các bộ xử lý thanh toán
PaymentProcessor <|.. StripeProcessor
PaymentProcessor <|.. PayPalProcessor

' Các mối liên kết cụ thể (Ví dụ về liên kết tự thân từ chú thích)
class "Employee" as Employee
Employee --> "báo cáo cho" Employee

@enduml

Kết luận

Thành thạo biểu đồ lớp UML là điều cần thiết đối với bất kỳ kiến trúc sư phần mềm hoặc nhà phát triển nào. Như đã chứng minh trong Nền tảng Giao đồ ăn Thống nhất nghiên cứu tình huống, UML cho phép chúng ta trực quan hóa các mối quan hệ phức tạp—chẳng hạn như sự khác biệt giữa một Xe hơi thừa kế từ một Phương tiện so với việc thực hiện một Giao diện Có thể điều khiển được giao diện.

Bằng cách tuân thủ nghiêm ngặt các quy tắc cú pháp liên quan đến bội số (1, , 1..) và quyền sở hữu (Thành phần so với Tập hợp), các nhóm có thể ngăn ngừa các lỗi kiến trúc, chẳng hạn như các bản ghi dữ liệu bị cô lập hoặc các thiết kế cứng nhắc khó mở rộng. Dù bạn đang thiết kế một hệ thống đăng nhập đơn giản hay một thị trường đa nhà cung cấp, một biểu đồ UML được thiết kế cẩn thận vẫn là công cụ hiệu quả nhất để truyền đạt tầm nhìn của bạn.