UML-类图

杜绝屎山,从我做起!

资源

正文

"在软件工程中,统一建模语言(UML)中的类图是一种静态结构图,它通过显示系统的类、它们的属性、操作(或方法)以及对象之间的关系来描述系统的结构。"

类图是面向对象建模的主要构建块。它用于应用结构的一般概念建模,以及将模型转换为编程代码的详细建模。类图也可用于数据建模。类图中的类表示主要元素、应用中的交互以及要编程的类。

在 UML 类图中,两个类之间可能有以下几种关系:

Mermaid
Loading diagram…

提示

接口继承为三角,聚合组合为菱形,依赖关联为箭头,弱虚强实指源头。

关联(Association)

  • 这是最常见的关系,表示类之间的一种“有”或“使用”关系。

  • 可以是双向或单向的。

  • 例如:一个 Person 类和一个 Car 类,表示一个人可能拥有一辆车。

Mermaid
Loading diagram…

{% tabs Association %}

C#
class Person
{
    public string Name { get; set; }
    public Car Car { get; set; }  // 关联关系,一个人拥有一辆车
}
 
class Car
{
    public string Model { get; set; }
}
javascript
class Person {
    constructor(name) {
        this.name = name;
        this.car = null;  // 关联关系,一个人拥有一辆车
    }
 
    setCar(car) {
        this.car = car;
    }
}
 
class Car {
    constructor(model) {
        this.model = model;
    }
}
 
const car = new Car("Toyota");
const person = new Person("John");
person.setCar(car);
console.log(person.name + " owns a " + person.car.model);
python
class Person:
    def __init__(self, name):
        self.name = name
        self.car = None  # 关联关系,一个人拥有一辆车
 
    def set_car(self, car):
        self.car = car
 
class Car:
    def __init__(self, model):
        self.model = model
 
car = Car("Toyota")
person = Person("John")
person.set_car(car)
 
print(f"{person.name} owns a {person.car.model}")

{% endtabs %}

聚合(Aggregation)

  • 聚合是一种特殊的关联,表示整体和部分的关系,整体可以存在而部分可以独立存在。

  • 聚合通常表示“一个整体包含多个部分”,但这些部分可以独立于整体存在。

Mermaid
Loading diagram…

{% tabs Aggregation %}

C#
class Department
{
    public string Name { get; set; }
    public List<Employee> Employees { get; set; } = new List<Employee>();  // 聚合关系,部门包含多个员工
}
 
class Employee
{
    public string Name { get; set; }
}
javascript
class Department {
    constructor(name) {
        this.name = name;
        this.employees = [];  // 聚合关系,部门包含多个员工
    }
 
    addEmployee(employee) {
        this.employees.push(employee);
    }
}
 
class Employee {
    constructor(name) {
        this.name = name;
    }
}
 
const department = new Department("Engineering");
const employee1 = new Employee("Alice");
const employee2 = new Employee("Bob");
 
department.addEmployee(employee1);
department.addEmployee(employee2);
 
console.log(department.name + " department has " + department.employees.length + " employees.");
python
class Department:
    def __init__(self, name):
        self.name = name
        self.employees = []  # 聚合关系,部门包含多个员工
 
    def add_employee(self, employee):
        self.employees.append(employee)
 
class Employee:
    def __init__(self, name):
        self.name = name
 
department = Department("Engineering")
employee1 = Employee("Alice")
employee2 = Employee("Bob")
 
department.add_employee(employee1)
department.add_employee(employee2)
 
print(f"{department.name} department has {len(department.employees)} employees.")

{% endtabs %}

组合(Composition)

  • 组合是聚合的一种特殊形式,表示部分不能独立于整体存在,整体和部分生命周期一致。

  • 例如:一个 House 类和 Room 类,房间无法在没有房子的情况下独立存在。

Mermaid
Loading diagram…

{% tabs Composition %}

C#
class House
{
    public string Address { get; set; }
    public Room Room { get; set; }  // 组合关系,房子包含一个房间,房间不能独立存在
}
 
class Room
{
    public string Type { get; set; }
}
javascript
class House {
    constructor(address) {
        this.address = address;
        this.room = new Room("Living Room");  // 组合关系,房子包含一个房间
    }
}
 
class Room {
    constructor(type) {
        this.type = type;
    }
}
 
const house = new House("123 Main St");
console.log(house.address + " has a " + house.room.type);
python
class House:
    def __init__(self, address):
        self.address = address
        self.room = Room("Living Room")  # 组合关系,房子包含一个房间
 
class Room:
    def __init__(self, type):
        self.type = type
 
house = House("123 Main St")
print(f"{house.address} has a {house.room.type}")

{% endtabs %}

继承(Inheritance)

  • 继承表示类之间的“是一个”关系,子类继承父类的属性和方法。
  • 子类可以继承父类的实现,也可以重写父类的功能。
Mermaid
Loading diagram…

{% tabs Inheritance %}

C#
class Animal
{
    public string Name { get; set; }
 
    public void Speak()
    {
        Console.WriteLine("Animal makes a sound.");
    }
}
 
class Dog : Animal  // 继承关系
{
    public void Bark()
    {
        Console.WriteLine("Dog barks.");
    }
}
javascript
class Animal {
    constructor(name) {
        this.name = name;
    }
 
    speak() {
        console.log(this.name + " makes a sound.");
    }
}
 
class Dog extends Animal {  // 继承关系
    constructor(name) {
        super(name);
    }
 
    bark() {
        console.log(this.name + " barks.");
    }
}
 
const dog = new Dog("Buddy");
dog.speak();  // 继承的方法
dog.bark();   // 子类特有的方法
python
class Animal:
    def __init__(self, name):
        self.name = name
 
    def speak(self):
        print(f"{self.name} makes a sound.")
 
class Dog(Animal):  # 继承关系
    def __init__(self, name):
        super().__init__(name)
 
    def bark(self):
        print(f"{self.name} barks.")
 
dog = Dog("Buddy")
dog.speak()  # 继承的方法
dog.bark()   # 子类特有的方法

{% endtabs %}

实现(Interface Implementation)

  • 表示类与接口之间的关系,类实现了某个接口所定义的行为。

  • 类可以实现多个接口。

Mermaid
Loading diagram…

{% tabs InterfaceImplementation %}

C#
interface IDriveable
{
    void Drive();
}
 
class Car : IDriveable  // 实现接口
{
    public void Drive()
    {
        Console.WriteLine("Car is driving.");
    }
}
  • JavaScript 本身不支持接口(interface),但可以通过类的结构模仿接口。

  • 可以通过某些约定(例如强制类实现特定方法)来实现类似接口的行为。

javascript
class Driveable {
    drive() {
        throw "This method must be implemented";
    }
}
 
class Car extends Driveable {  // 实现Driveable接口的行为
    constructor(model) {
        super();
        this.model = model;
    }
 
    drive() {
        console.log(this.model + " is driving.");
    }
}
 
const car = new Car("Toyota");
car.drive();
  • Python 没有显式的接口,但可以通过抽象类和方法来模拟接口的概念。

  • 使用 abc 模块定义抽象基类(ABC)来模拟接口。

python
from abc import ABC, abstractmethod
 
class Driveable(ABC):
    @abstractmethod
    def drive(self):
        pass
 
class Car(Driveable):  # 实现 Driveable 接口的行为
    def __init__(self, model):
        self.model = model
 
    def drive(self):
        print(f"{self.model} is driving.")
 
car = Car("Toyota")
car.drive()

{% endtabs %}

依赖(Dependency)

  • 依赖关系表示一个类使用了另一个类,但这种关系是暂时的或松散的,通常表示方法参数、局部变量等依赖。

  • 例如:一个 Car 类依赖于 Engine 类,Car 类在启动时会调用 Engine 类的功能。

Mermaid
Loading diagram…

{% tabs Dependency %}

C#
class Car
{
    public void StartEngine(Engine engine)  // 依赖关系,车需要发动机来启动
    {
        engine.Start();
    }
}
 
class Engine
{
    public void Start()
    {
        Console.WriteLine("Engine starts.");
    }
}
javascript
class Engine {
    start() {
        console.log("Engine starts.");
    }
}
 
class Car {
    startEngine(engine) {  // 依赖关系,车需要发动机来启动
        engine.start();
    }
}
 
const engine = new Engine();
const car = new Car();
car.startEngine(engine);
python
class Engine:
    def start(self):
        print("Engine starts.")
 
class Car:
    def start_engine(self, engine):  # 依赖关系,车需要发动机来启动
        engine.start()
 
engine = Engine()
car = Car()
car.start_engine(engine)

{% endtabs %}