当前位置: 首页 > article >正文

深入理解系统:UML类图

UML类图

类图(class diagram) 描述系统中的对象类型,以及存在于它们之间的各种静态关系

正向工程(forward engineering)在编写代码之前画UML图。
逆向工程(reverse engineering)从已有代码建造UML图,目的是帮助人们理解代码。

案例1:电商系统类图

在这里插入图片描述

# UML类图元素:类、属性、方法、继承、关联、聚合
from typing import Listclass User:def __init__(self, user_id: str, name: str):self.user_id = user_id  # 公有属性self._name = name       # 保护属性self.__password = ""    # 私有属性def login(self, password: str) -> bool:  # 公有方法"""验证用户登录"""return password == self.__passwordclass Customer(User):  # 继承关系 (泛化)def __init__(self, user_id: str, name: str):super().__init__(user_id, name)self.cart = ShoppingCart()  # 组合关系 (强拥有)def place_order(self) -> Order:"""创建订单"""return Order(self, self.cart.items)class Seller(User):  # 继承关系def __init__(self, user_id: str, name: str, store: Store):super().__init__(user_id, name)self.store = store  # 关联关系def add_product(self, product: Product):"""添加商品到店铺"""self.store.products.append(product)class Product:def __init__(self, product_id: str, name: str, price: float):self.product_id = product_idself.name = nameself.price = priceclass ShoppingCart:def __init__(self):self.items: List[Product] = []  # 聚合关系 (弱拥有)def add_item(self, product: Product):self.items.append(product)def calculate_total(self) -> float:return sum(item.price for item in self.items)class Order:def __init__(self, customer: Customer, items: List[Product]):self.customer = customer  # 关联关系self.items = itemsself.status = "Pending"def process_payment(self, payment: PaymentProcessor):  # 依赖关系payment.process(self.calculate_total())def calculate_total(self) -> float:return sum(item.price for item in self.items)class Store:def __init__(self, store_id: str, name: str):self.store_id = store_idself.name = nameself.products: List[Product] = []  # 聚合关系# 接口实现 (依赖倒置)
class PaymentProcessor(ABC):  # 抽象类/接口@abstractmethoddef process(self, amount: float):passclass CreditCardProcessor(PaymentProcessor):  # 实现关系def process(self, amount: float):print(f"Processing credit card payment: ${amount:.2f}")class PayPalProcessor(PaymentProcessor):  # 实现关系def process(self, amount: float):print(f"Processing PayPal payment: ${amount:.2f}")

案例2:车辆租赁系统类图

在这里插入图片描述

# UML类图元素:抽象类、枚举、组合、聚合、依赖
from abc import ABC, abstractmethod
from enum import Enum
from datetime import dateclass VehicleType(Enum):  # 枚举类CAR = 1TRUCK = 2SUV = 3MOTORCYCLE = 4class AbstractVehicle(ABC):  # 抽象类def __init__(self, license_plate: str, model: str, year: int):self.license_plate = license_plateself.model = modelself.year = yearself.available = True@abstractmethoddef get_rental_rate(self) -> float:passclass Car(AbstractVehicle):  # 继承def __init__(self, license_plate: str, model: str, year: int, seats: int):super().__init__(license_plate, model, year)self.seats = seatsdef get_rental_rate(self) -> float:  # 实现抽象方法return 50.0 + (self.seats * 5)class Truck(AbstractVehicle):  # 继承def __init__(self, license_plate: str, model: str, year: int, capacity: float):super().__init__(license_plate, model, year)self.capacity = capacity  # 载重能力(吨)def get_rental_rate(self) -> float:return 100.0 + (self.capacity * 20)class RentalAgency:def __init__(self, name: str):self.name = nameself.fleet: List[AbstractVehicle] = []  # 聚合self.rentals: List[RentalContract] = []  # 组合def add_vehicle(self, vehicle: AbstractVehicle):self.fleet.append(vehicle)def rent_vehicle(self, customer: Customer, vehicle: AbstractVehicle, start_date: date, end_date: date):if vehicle.available:contract = RentalContract(customer, vehicle, start_date, end_date)self.rentals.append(contract)vehicle.available = Falsereturn contractreturn Noneclass Customer:def __init__(self, customer_id: str, name: str):self.customer_id = customer_idself.name = nameself.license_number = ""class RentalContract:  # 组合类def __init__(self, customer: Customer, vehicle: AbstractVehicle, start_date: date, end_date: date):self.customer = customerself.vehicle = vehicleself.start_date = start_dateself.end_date = end_dateself.total_cost = self.calculate_cost()def calculate_cost(self) -> float:days = (self.end_date - self.start_date).daysreturn days * self.vehicle.get_rental_rate()def generate_invoice(self, printer: InvoicePrinter):  # 依赖关系printer.print_invoice(self)class InvoicePrinter:  # 工具类def print_invoice(self, contract: RentalContract):print(f"Invoice for {contract.customer.name}")print(f"Vehicle: {contract.vehicle.model}")print(f"Total: ${contract.total_cost:.2f}")

案例3:学校管理系统类图

在这里插入图片描述

# UML类图元素:多重继承、接口实现、依赖、关联
from abc import ABC, abstractmethod
from datetime import dateclass Person:def __init__(self, name: str, birth_date: date):self.name = nameself.birth_date = birth_datedef get_age(self) -> int:today = date.today()return today.year - self.birth_date.yearclass Researcher(ABC):  # 接口@abstractmethoddef conduct_research(self, topic: str):passclass Teacher(Person):  # 单继承def __init__(self, name: str, birth_date: date, department: str):super().__init__(name, birth_date)self.department = departmentself.courses: List[Course] = []  # 双向关联def assign_course(self, course: 'Course'):self.courses.append(course)course.teacher = selfclass Professor(Teacher, Researcher):  # 多重继承def __init__(self, name: str, birth_date: date, department: str, title: str):Teacher.__init__(self, name, birth_date, department)self.title = titledef conduct_research(self, topic: str):  # 实现接口print(f"Conducting research on {topic}")def supervise_phd(self, student: 'PhdStudent'):student.advisor = selfclass Student(Person):def __init__(self, name: str, birth_date: date, student_id: str):super().__init__(name, birth_date)self.student_id = student_idself.enrolled_courses: List['Course'] = []  # 关联def enroll(self, course: 'Course'):self.enrolled_courses.append(course)course.students.append(self)class PhdStudent(Student, Researcher):  # 多重继承def __init__(self, name: str, birth_date: date, student_id: str, research_topic: str):Student.__init__(self, name, birth_date, student_id)self.research_topic = research_topicself.advisor: Professor = None  # 关联def conduct_research(self, topic: str):  # 实现接口print(f"Conducting PhD research on {topic}")class Course:def __init__(self, course_code: str, name: str):self.course_code = course_codeself.name = nameself.teacher: Teacher = None  # 双向关联self.students: List[Student] = []  # 双向关联def add_student(self, student: Student):self.students.append(student)student.enrolled_courses.append(self)class Department:def __init__(self, name: str):self.name = nameself.faculty: List[Teacher] = []  # 聚合self.courses: List[Course] = []  # 聚合def hire_teacher(self, teacher: Teacher):self.faculty.append(teacher)def add_course(self, course: Course):self.courses.append(course)class EnrollmentSystem:  # 依赖多个类def enroll_student(self, student: Student, course: Course):if student not in course.students:student.enroll(course)return Truereturn False

综合案例:带抽象接口和静态方法的电商系统

在这里插入图片描述

from abc import ABC, abstractmethod
from datetime import datetime# 抽象接口:日志服务
class ILogger(ABC):@abstractmethoddef log(self, message: str):pass# 实现接口的类
class ConsoleLogger(ILogger):def log(self, message: str):print(f"[{datetime.now()}] {message}")class FileLogger(ILogger):def __init__(self, filename: str):self.filename = filenamedef log(self, message: str):with open(self.filename, "a") as file:file.write(f"[{datetime.now()}] {message}\n")# 带静态方法的工具类
class ValidationUtils:@staticmethoddef is_valid_email(email: str) -> bool:return "@" in email and "." in email.split("@")[-1]@staticmethoddef is_valid_phone(phone: str) -> bool:return phone.isdigit() and len(phone) >= 7# 使用接口和静态方法的类
class UserService:def __init__(self, logger: ILogger):self.logger = loggerdef register_user(self, name: str, email: str, phone: str):# 使用静态方法验证if not ValidationUtils.is_valid_email(email):self.logger.log(f"Invalid email: {email}")return Falseif not ValidationUtils.is_valid_phone(phone):self.logger.log(f"Invalid phone: {phone}")return False# 注册逻辑...self.logger.log(f"User {name} registered with {email}")return True# 工厂类(使用静态方法创建对象)
class LoggerFactory:@staticmethoddef create_logger(logger_type: str) -> ILogger:if logger_type == "console":return ConsoleLogger()elif logger_type == "file":return FileLogger("app.log")else:raise ValueError("Invalid logger type")

UML类图要素总结

UML要素Python代码表现UML符号说明
类(Class)class Person:矩形框包含类名、属性和方法
抽象类class AbstractVehicle(ABC):斜体类名包含抽象方法
接口class Interface(ABC): + @abstractmethod<<interface>> + 斜体名称只包含抽象方法
属性self.name: str+name: str+公有, -私有, #保护
方法def get_age(self):
静态方法: @staticmethod 装饰器
类方法:@classmethod 装饰器
抽象方法: @abstractmethod 装饰器
+get_age(): int
静态方法:{static} 标记或方法名下划线
类方法:{classmethod} 标记
抽象方法:{abstract} 标记 + 斜体方法名
类行为定义
继承class Teacher(Person):空心三角+实线泛化关系(is-a)
实现class Professor(Researcher):空心三角+虚线实现接口方法
组合一对一:self.cart = ShoppingCart()
一对多:self.car=[Wheel(),Wheel(),Wheel(),Wheel(),Engine()]
实心菱形+实线强拥有关系(同生命周期)
聚合self.fleet: List[Vehicle] = []空心菱形+实线弱拥有关系(可独立存在)
关联self.teacher: Teacher = None实线箭头对象间持久引用关系
依赖def process_payment(payment):虚线箭头临时使用(方法参数或局部变量中)
枚举class VehicleType(Enum):<<enumeration>>固定值集合
多重继承class Professor(Teacher, Researcher):多个空心三角继承多个父类

一些细节

关于【箭头方向】

箭头方向在UML中表示导航性(Navigability):

箭头类型表示代码等价
无箭头双向导航(默认)双方相互持有引用
单向导航只有源头类知道目标类
双向导航双方相互持有引用
◁/▷箭头端为被引用方箭头指向的类是被持有的类

关于类关系的虚实

以下是对类图中类关系图形的完整总结,重点说明实心/空心、实线/虚线的区别:

1. 实线 vs 虚线
线条类型关系强度生命周期代码对应典型关系
实线强关系可能绑定成员变量(属性)关联、聚合、组合
虚线弱关系无绑定方法参数/局部变量依赖、接口实现
2. 实心 vs 空心
填充类型所有权关系强度典型符号位置代表关系
实心强所有权最强菱形端组合关系
空心弱所有权中等菱形端/三角端聚合/继承/实现
完整关系对比图

在这里插入图片描述

关于【多重性】

多重性定义对象之间的数量关系,常见表示法:

表示法含义示例说明
1恰好1个每个人有1个心脏(组合关系)
0..10或1个学生可能有0或1个导师(关联关系)
1..*1个或多个订单必须包含至少1个商品(组合关系)
0..*0或多个部门可以有0或多个员工(聚合关系)
n恰好n个三角形有3条边(组合关系)
m..nm到n个课程有3-50名学生(关联关系)
*无限多个(同0..*社交媒体用户有多个好友(关联关系)

汇总

要素类型UML表示法代码表现多重性箭头方向生命周期关系
类(Class)矩形框(类名、属性、方法)class MyClass:不适用独立存在
抽象类类名斜体class MyClass(ABC):不适用独立存在
接口<<interface>> + 类框或圆圈class MyInterface(ABC):不适用独立存在
枚举<<enumeration>> + 枚举值class MyEnum(Enum):不适用独立存在
属性[可见性] 属性名: 类型 [= 默认值]self.attr = value不适用随对象存在
方法[可见性] 方法名(参数): 返回类型def method(self):不适用随对象存在
抽象方法斜体或{abstract}@abstractmethod不适用随抽象类存在
静态方法{static} 或下划线@staticmethod不适用类加载时存在
类方法{classmethod}@classmethod不适用类加载时存在
继承(泛化)空心三角箭头 + 实线class Child(Parent):不适用子类→父类子类依赖父类
接口实现空心三角箭头 + 虚线实现接口所有方法不适用实现类→接口实现类依赖接口
关联实线(可带箭头)类属性为另一类对象两端可设置可选(表示导航方向)相互独立
聚合空心菱形 + 实线外部传入对象(self.parts = [ext_obj])整体端通常为1菱形→整体部分可独立于整体
组合实心菱形 + 实线内部创建对象(self.part = Part())整体端通常为1菱形→整体部分依赖整体
依赖虚线箭头局部变量/参数/静态调用不适用使用方→被依赖方临时关系

相关文章:

深入理解系统:UML类图

UML类图 类图&#xff08;class diagram&#xff09; 描述系统中的对象类型&#xff0c;以及存在于它们之间的各种静态关系。 正向工程&#xff08;forward engineering&#xff09;在编写代码之前画UML图。 逆向工程&#xff08;reverse engineering&#xff09;从已有代码建…...

C# 中的 IRecipient

IRecipient<TMessage> 是 .NET 中消息传递机制的重要组成部分&#xff0c;特别是在 MVVM (Model-View-ViewModel) 模式中广泛使用。下面我将详细介绍这一机制及其应用。 基本概念 IRecipient<TMessage> 是 .NET Community Toolkit 和 MVVM Toolkit 中定义的一个接…...

大模型RNN

RNN&#xff08;循环神经网络&#xff09;是一种专门处理序列数据的神经网络架构&#xff0c;在自然语言处理&#xff08;NLP&#xff09;、语音识别、时间序列分析等领域有广泛应用。其核心作用是捕捉序列中的时序依赖关系&#xff0c;即当前输出不仅取决于当前输入&#xff0…...

Python环境搭建竞赛技术文章大纲

竞赛背景与意义 介绍Python在数据科学、机器学习等领域的重要性环境搭建对于竞赛项目效率的影响常见竞赛平台对Python环境的特殊要求 基础环境准备 操作系统选择与优化&#xff08;Windows/Linux/macOS&#xff09;Python版本选择&#xff08;3.x推荐版本&#xff09;解释器…...

Redisson - 实现延迟队列

Redisson 延迟队列 Redisson 是基于 Redis 的一款功能强大的 Java 客户端。它提供了诸如分布式锁、限流器、阻塞队列、延迟队列等高可用、高并发组件。 其中&#xff0c;RDelayedQueue 是对 Redis 数据结构的高阶封装&#xff0c;能让你将消息延迟一定时间后再进入消费队列。…...

软件工程的定义与发展历程

文章目录 一、软件工程的定义二、软件工程的发展历程1. 前软件工程时期(1940s-1960s)2. 软件工程诞生(1968)3. 结构化方法时期(1970s)4. 面向对象时期(1980s)5. 现代软件工程(1990s-至今) 三、软件工程的发展趋势 一、软件工程的定义 软件工程是应用系统化、规范化、可量化的方…...

艾利特协作机器人:重新定义工业涂胶场景的精度革命

品牌使命与技术基因 作为全球协作机器人领域成长最快的企业之一&#xff0c;艾利特始终聚焦于解决工业生产中的人机协作痛点。在汽车制造、3C电子、新能源等领域的涂胶工艺场景中&#xff0c;我们通过自主研发的EC系列协作机器人&#xff0c;实现了&#xff1a; 空间利用率&a…...

第十三节:第五部分:集合框架:集合嵌套

集合嵌套案例分析 代码&#xff1a; package com.itheima.day27_Collection_nesting;import java.util.*;/*目标:理解集合的嵌套。 江苏省 "南京市","扬州市","苏州市","无锡市","常州市" 湖北省 "武汉市","…...

Java设计模式之观察者模式详解

一、观察者模式简介 观察者模式&#xff08;Observer Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了对象之间的一对多依赖关系。当一个对象&#xff08;主题&#xff09;的状态发生改变时&#xff0c;所有依赖于它的对象&#xff08;观察者&#xff09;都会自…...

freeRTOS 消息队列之一个事件添加到消息队列超时怎么处理

一 消息队列的结构框图 xTasksWaitingToSend‌&#xff1a;这个列表存储了所有因为队列已满而等待发送消息的任务。当任务尝试向一个已满的队列发送消息时&#xff0c;该任务会被挂起并加入到xTasksWaitingToSend列表中&#xff0c;直到队列中有空间可用‌&#xff0c; xTasksW…...

十八、【用户认证篇】安全第一步:基于 JWT 的前后端分离认证方案

【用户认证篇】安全第一步:基于 JWT 的前后端分离认证方案 前言什么是 JWT (JSON Web Token)?准备工作第一部分:后端 Django 配置 JWT 认证1. 安装 `djangorestframework-simplejwt`2. 在 `settings.py` 中配置 `djangorestframework-simplejwt`3. 在项目的 `urls.py` 中添加…...

RabbitMQ 开机启动配置教程

RabbitMQ 开机启动配置教程 在本教程中&#xff0c;我们将详细介绍如何配置 RabbitMQ 以实现开机自动启动。此配置适用于手动安装的 RabbitMQ 版本。 环境准备 操作系统&#xff1a;CentOS 7RabbitMQ 版本&#xff1a;3.8.4Erlang 版本&#xff1a;21.3 步骤 1. 安装 Erla…...

Authpf(OpenBSD)认证防火墙到ssh连接到SSH端口转发技术栈 与渗透网络安全的关联 (RED Team Technique )

目录 &#x1f50d; 1. Authpf概述与Shell设置的作用 什么是Authpf&#xff1f; Shell设置为/usr/sbin/authpf的作用与含义 &#x1f6e0;️ 2. Authpf工作原理与防火墙绕过机制 技术栈 工作原理 防火墙绕过机制 Shell关联 &#x1f310; 3. Authpf与SSH认证及服务探测…...

组合与排列

组合与排列主要有两个区别&#xff0c;区别在于是否按次序排列和符号表示不同。 全排列&#xff1a; 从n个不同元素中任取m&#xff08;m≤n&#xff09;个元素&#xff0c;按照一定的顺序排列起来&#xff0c;叫做从n个不同元素中取出m个元素的一个排列。当mn时所有的排列情况…...

神经网络-Day45

目录 一、tensorboard的基本操作1.1 发展历史1.2 tensorboard的原理 二、tensorboard实战2.1 cifar-10 MLP实战2.2 cifar-10 CNN实战 在神经网络训练中&#xff0c;为了帮助理解&#xff0c;借用了很多的组件&#xff0c;比如训练进度条、可视化的loss下降曲线、权重分布图&…...

【西门子杯工业嵌入式-1-基本环境与空白模板】

西门子杯工业嵌入式-1-基本环境与空白模板 项目资料一、软件安装与环境准备1. 安装MDK52. 安装驱动3. 安装GD32F470支持包 二、工程目录结构建议三、使用MDK创建工程流程1. 新建工程2. 添加工程组&#xff08;Group&#xff09;3. 添加源文件 四、编译配置设置&#xff08;Opti…...

Apache Druid

目录 Apache Druid是什么&#xff1f; CVE-2021-25646(Apache Druid代码执行漏洞) Apache Druid是什么&#xff1f; Apache Druid是一个高性能、分布式的数据存储和分析系统。设计用于处理大量实时数据&#xff0c;并进行低延迟的查询。它特别适合用于分析大规模日志、事件数据…...

使用深蓝词库软件导入自定义的词库到微软拼音输入法

我这有一个人员名单&#xff0c;把它看作一个词库&#xff0c;下面我演示一下如何把这个词库导入微软输入法 首先建一个text文件&#xff0c;一行写一个词条 下载深蓝词库 按照我这个配置&#xff0c;点击转换&#xff0c;然后在桌面微软输入法那右键&#xff0c;选择设置 点…...

Docker快速部署AnythingLLM全攻略

Docker版AnythingLLM安装指南 环境准备 确保已安装: Docker Engine 20.10.14+Docker Compose 2.5.0+验证安装: docker --version && docker compose version安装步骤 创建持久化存储目录: mkdir -p ~/anythingllm/database ~/anythingllm/files运行容器(基础配置)…...

使用Node.js分片上传大文件到阿里云OSS

阿里云OSS的分片上传&#xff08;Multipart Upload&#xff09;是一种针对大文件优化的上传方式&#xff0c;其核心流程和关键特性如下&#xff1a; 1. ‌核心流程‌ 分片上传分为三个步骤&#xff1a; 初始化任务‌&#xff1a;调用InitiateMultipartUpload接口创建上传任务…...

高性能分布式消息队列系统(四)

八、客户端模块的实现 客户端实现的总体框架 在 RabbitMQ 中&#xff0c;应用层提供消息服务的核心实体是 信道&#xff08;Channel&#xff09;。 用户想要与消息队列服务器交互时&#xff0c;通常不会直接操作底层的 TCP 连接&#xff0c;而是通过信道来进行各种消息的发布…...

C#异步编程:从线程到Task的进化之路

一、没有异步编程之前的时候 在异步编程出现之前,程序主要采用同步编程模型。这种模型下,所有操作按顺序执行,当一个操作(如I/O读写、网络请求)阻塞时,整个程序会被挂起,导致资源利用率低和响应延迟高。具体问题包括: 阻塞执行:同步代码在执行耗时操作时(如文件读取…...

[论文阅读] 人工智能+软件工程 | 用大模型优化软件性能

用大模型优化软件性能&#xff1f;这篇论文让代码跑出新速度&#xff01; arXiv:2506.01249 SysLLMatic: Large Language Models are Software System Optimizers Huiyun Peng, Arjun Gupte, Ryan Hasler, Nicholas John Eliopoulos, Chien-Chou Ho, Rishi Mantri, Leo Deng, K…...

复变函数中的对数函数及其MATLAB演示

复变函数中的对数函数及其MATLAB演示 引言 在实变函数中&#xff0c;对数函数 ln ⁡ x \ln x lnx定义在正实数集上&#xff0c;是一个相对简单的概念。然而&#xff0c;当我们进入复变函数领域时&#xff0c;对数函数展现出更加丰富和复杂的性质。本文将介绍复变函数中对数函…...

【Linux】Linux程序地址基础

参考博客&#xff1a;https://blog.csdn.net/sjsjnsjnn/article/details/125533127 一、地址空间的阐述 1.1 程序地址空间 下面的图片展示了程序地址空间的组成结构 我们通过代码来验证一下 int g_unval; int g_val 100;int main(int argc, char *argv[]);void test1() {i…...

React 项目初始化与搭建指南

React 项目初始化有多种方式&#xff0c;可以选择已有的脚手架工具快速创建项目&#xff0c;也可以自定义项目结构并使用构建工具实现项目的构建打包流程。 1. 脚手架方案 1.1. Vite 通过 Vite 创建 React 项目非常简单&#xff0c;只需一行命令即可完成。Vite 的工程初始化…...

将图形可视化工具的 Python 脚本打包为 Windows 应用程序

前文我们已经写了一个基于python的tkinter库和matplotlib库的图形可视化工具。 基于Python的tkinter库的图形可视化工具&#xff08;15种图形的完整代码&#xff09;:基于Python的tkinter库的图形可视化工具&#xff08;15种图形的完整代码&#xff09;-CSDN博客 在前文基础上&…...

AWS DocumentDB vs MongoDB:数据库的技术抉择

随着非关系型数据库在现代应用中的广泛应用&#xff0c;文档型数据库因其灵活的结构与出色的扩展性&#xff0c;逐渐成为企业开发与架构设计中的核心选择。在众多文档数据库中&#xff0c;MongoDB 凭借其成熟生态与社区支持占据主导地位&#xff1b;与此同时&#xff0c;AWS 提…...

无人机军用与民用技术对比分析

一、材料区别 军用无人机&#xff1a; 1. 高强度特种材料&#xff1a; 大量使用钛合金、碳纤维复合材料&#xff0c;兼顾轻量化与高强度&#xff0c;提升抗冲击性和隐身性能。 关键部件依赖进口材料。 2. 隐身涂层&#xff1a; 采用雷达吸波材料和低红外特征涂料&#xf…...

刷leetcode hot100--矩阵6/1

1.螺旋矩阵【很久】6/1【感觉就是思路的搬运工&#xff0c;没完全理解】 54. 螺旋矩阵 - 力扣&#xff08;LeetCode&#xff09; 原来想 但是如果是奇数矩阵&#xff0c;遍历不到中间 解决思路&#xff1a; 用left,right,top,down标记/限定每次遍历的元素&#xff0c;每次从…...