统一建模语言UML之类图(Class Diagram)(表示|关系|举例)

文章目录

  • 1.UML
  • 2.Class Diagram
    • 2.1 类图的表示
    • 2.2 类间的关系
      • 2.2.1 关联
      • 2.2.2 聚合
      • 2.2.3 组合
      • 2.2.4 泛化(继承)
      • 2.2.5 实现(接口实现)
      • 2.2.6 依赖
    • 2.3 类图的作用

参考:Class Diagram | Unified Modeling Language (UML)
UML是软件设计和面向对象编程中常用的一种标准化建模语言,对于可视化系统结构和功能非常有用,类图有多种不同类型的图:用例图,类图,时序图,活动图和状态图,每类图都有规范的表示,不局限于语言,本文介绍以下内容
(1)UML的图分类
(2)类图的表示
(3)类图的关系
(4)类图的作用

1.UML

Unified Modeling Language(UML)是一种标准化的建模语言,用于在软件系统开发过程中可视化、描述和设计软件的结构与行为。UML 提供了一系列图表,帮助开发人员、系统架构师以及相关人员交流系统的设计和功能。UML 包括许多不同类型的图:

  • 用例图(Use Case Diagram):描述系统的功能需求以及外部参与者的交互
  • 类图(Class Diagram):描述系统的静态结构,展示类、属性、方法以及类之间的关系
  • 时序图(Sequence Diagram):展示对象之间的消息传递顺序,描述时间序列中的动态行为
  • 活动图(Activity Diagram):用于表示系统中的流程和业务逻辑
  • 状态图(State Diagram):描述系统或对象的状态以及状态之间的转换

2.Class Diagram

2.1 类图的表示

在类图中,类用方框表示,每个方框包含三个部分:类名,属性和方法,方框之间的连接线说明这些类的关系。类图提供了系统设计的高级概述,有助于沟通和记录软件的结构。它们是面向对象设计的基本工具,在软件开发生命周期中起着至关重要的作用。

在这里插入图片描述
如图所示的方框为类Car的类图表示

  • Class Name:第一个小框描述了类名,通常放在方框中间加粗,类民首字母大写
  • Attributes:第二个小框介绍了类的属性(字段),包括属性名,属性的可见性和数据类型
  • Methods:第三个小框介绍了类的方法,代表了类的行为函数,包括可见性,返回类型和参数
  • Visibility:可见性表示了属性和方法的可获取水平
    (1)+:public公共,对所有类可见
    (2)-:private私有,仅在类内可见
    (3)#:protected保护,对子类可见
    (4)~:包或默认可见性,对同一包中的类可见
  • Parameter:方法中的参数显示了类之间的信息流动
    (1)in:输入参数是从调用对象(client)到被调用对象(server)的参数
    (2)out:输出参数是从被调用对象(server)到调用对象(client)的参数
    (2)inout:输入输出参数同时作为输入和输出,在client和server之间进行信息流通

2.2 类间的关系

在类图中,类之间的关系有以下几种:
在这里插入图片描述
比较常见的分类是6种:关联,聚合,组合,泛化(继承),实现,依赖,还有一些概念更细分的,比如直接关联,使用依赖等。

关系描述
关联Association表示类之间的长期持久关系,一个类持有另一个类的引用,通常通过成员变量表示
聚合Aggregation整体和部分关系,部分可以独立于整体
组合Composition整体和部分关系,部分不能独立于整体
泛化Generalization子类继承父类属性和方法,可扩展和重写
实现Realization通过抽象类定义接口,客户端和实现解耦
依赖Dependency表示类之间临时的关系,一个类需要短暂使用另一个类的某个功能,通常通过方法调用实现

2.2.1 关联

此处介绍两种:关联和直接关联,由于概念比较类似放在一个小节

(1)关联Association:是泛指两个类之间的关系,可以是双向或单向,也可以是弱耦合的逻辑联系,用直线表示

在这里插入图片描述

关联举例:选课系统中学生和课程之间是双向关联,学生可以注册多门课程,每门课程可以有多个学生,Student类和 Course类存在关联关系,但是并不代表Student类直接引用 Course类的实例。如下面代码所示,student1和course1的实例创建是独立的,但是student1中的enroll方法会用到course1,course1的add_student也会添加student1

class Student:def __init__(self, name):self.name = nameself.courses = []  # 一个学生可以注册多门课程def enroll(self, course):  # 学生注册课程,课程添加学生self.courses.append(course)course.add_student(self)class Course:def __init__(self, title):self.title = titleself.students = []  # 一门课程可以有多个学生def add_student(self, student):  self.students.append(student)# 创建实例
student1 = Student("Alice")
course1 = Course("Math")# 学生注册课程
student1.enroll(course1)

(2)直接关联Direct Association:强调单向依赖关系,一个类直接持有或依赖另一个类的实例,用带单向箭头的直线表示,箭头指向被持有的类。

直接关联是关联的一种更具体的表现,表示类之间有更明确的耦合关系

在这里插入图片描述

直接关联举例:学生和身份证之间存在一种直接关联。每个学生都必须有一个身份证,学生对象直接持有身份证对象。Student类和IDCard类之间有一个单向的直接关联,这是一种更强的依赖关系,表示Student 类的对象必须持有一个 IDCard 类的对象才能正常工作。如下面代码所示,student的实例创建必须用到id_card实例

class IDCard:def __init__(self, card_number):self.card_number = card_numberclass Student:def __init__(self, name, id_card):self.name = nameself.id_card = id_card  # 学生直接持有身份证的引用# 创建身份证实例
id_card = IDCard("123456789")
student = Student("Alice", id_card)# 访问学生的身份证信息
print(student.id_card.card_number)  # 输出: 123456789

2.2.2 聚合

  • 聚合Aggregation:一种特殊的关联形式,表示整体—部分(whole-part)关系,它表示一种更强的关系,其中一个类(整体)包含或由另一个类(部分)组成,在这种关系中,子类可以独立于其父类而存在。用带空心菱形箭头的直线表示,箭头指向整体
    在这里插入图片描述

聚合举例:公司拥有员工,但是员工可以在没有公司的情况下存在。换句话说,公司雇佣了员工,但员工可以辞职并加入另一家公司,因此公司和员工之间的关系是聚合。Company 是整体,Employee 是部分,如下面代码所示,company实例由employee1和employee2实例组成,但是删除company并不会影响employee1和employee2

class Employee:def __init__(self, name):self.name = namedef work(self):print(f"{self.name} is working.")class Company:def __init__(self, name):self.name = nameself.employees = []  # 聚合关系,公司由多个员工组成def hire(self, employee):self.employees.append(employee)print(f"{employee.name} has been hired by {self.name}.")def list_employees(self):print(f"{self.name} has the following employees:")for emp in self.employees:print(f"- {emp.name}")# 创建公司和员工实例
employee1 = Employee("Alice")
employee2 = Employee("Bob")
company = Company("TechCorp")# 公司雇佣员工
company.hire(employee1)
company.hire(employee2)# 公司列出员工
company.list_employees()# 即使公司不存在,员工仍然可以存在
del company
employee1.work()  # 输出: Alice is working.

2.2.3 组合

  • 组合Composition:一种更强的聚合形式,表示更重要的所有权或依赖关系。在组合中,部分类不能独立于整体类而存在。组合带实心菱形箭头的直线表示,箭头指向整体

在这里插入图片描述

组合举例:手机里通讯录和联系人的关系是组合关系,如果通讯录被删除,那么里面的联系人也会删除,也就是说联系人不能独立于通讯录存在。ContactBook 是整体,Contact 是部分

class Contact:def __init__(self, name, phone):self.name = nameself.phone = phonedef display_contact(self):print(f"Name: {self.name}, Phone: {self.phone}")class ContactBook:def __init__(self):self.contacts = []  # 组合关系,通讯录拥有多个联系人def add_contact(self, name, phone):contact = Contact(name, phone)  # 创建联系人的同时,直接把它归属到通讯录self.contacts.append(contact)# 创建通讯录实例
contact_book = ContactBook()# 向通讯录添加联系人
contact_book.add_contact("Alice", "123-456-7890")
contact_book.add_contact("Bob", "987-654-3210")
# 删除通讯录
del contact_book
# 联系人对象也会随之销毁,无法独立存在

2.2.4 泛化(继承)

  • 泛化Generalization(继承Inheritance):表示类之间的“is-a”关系,其中一个类(subclass或child)继承另一个类(supclass或parent)的属性和行为,继承使得子类能够复用父类的代码,同时可以扩展或重写父类的功能。用一条带空心三角箭头的实线表示,箭头指向父类
    在这里插入图片描述

继承举例:一个银行账户下的储蓄账户和信用账户可以共用这个银行账户的信息,BankAccount是父类,SavingsAccount 是子类,CreditAccount 是子类

# 父类:BankAccount
class BankAccount:def __init__(self, account_number, balance):self.account_number = account_number  # 账户号码self.balance = balance  # 账户余额def deposit(self, amount):"""存款方法"""self.balance += amountprint(f"Deposited {amount}. New balance: {self.balance}")def withdraw(self, amount):"""取款方法"""if amount > self.balance:print("Insufficient funds!")else:self.balance -= amountprint(f"Withdrew {amount}. New balance: {self.balance}")# 子类:SavingsAccount
class SavingsAccount(BankAccount):def __init__(self, account_number, balance, interest_rate):super().__init__(account_number, balance)self.interest_rate = interest_rate  # 储蓄账户的利率def add_interest(self):"""添加利息"""interest = self.balance * self.interest_rateself.balance += interestprint(f"Interest added: {interest}. New balance: {self.balance}")# 子类:CreditAccount
class CreditAccount(BankAccount):def __init__(self, account_number, balance, credit_limit):super().__init__(account_number, balance)self.credit_limit = credit_limit  # 信用账户的信用额度def withdraw(self, amount):"""重写父类的取款方法,允许透支"""if amount > self.balance + self.credit_limit:print("Exceeds credit limit!")else:self.balance -= amountprint(f"Withdrew {amount}. New balance: {self.balance}")# 测试代码
savings = SavingsAccount("12345", 1000, 0.05)
savings.deposit(500)
savings.add_interest()credit = CreditAccount("67890", 500, 1000)
credit.withdraw(200)
credit.withdraw(1500)  # 允许透支
credit.withdraw(2000)  # 超过信用额度

2.2.5 实现(接口实现)

  • 实现Realization(接口实现Interface Implementation):是在面向对象设计中,通过接口或抽象类来定义某些功能,来描述某一组行为的约定,而具体的实现由不同的类来完成。可以避免直接依赖具体类,而是依赖接口或抽象类,从而实现代码的解耦。用带空心三角箭头的虚线表示,箭头指向接口
    在这里插入图片描述

实现举例:有一个支付系统,它支持多种支付方式,如信用卡支付,PayPal 支付和比特币支付,每种支付方式都有自己的具体实现方式,但它们都应该符合统一的支付行为,比如 pay()。比如下面代码中,IPayment是一个抽象类,也就是客户端接口,声明了一个pay()方法,但是没有具体实现,而CreditCardPayment,PayPalPayment和BitcoinPayment都会各自具体实现pay(),对于客户端代码process_payment传入任何一个payment_method,都可以使用pay(),客户端代码不关心具体是哪种支付方式,只需要知道它实现了IPayment 接口即可。

from abc import ABC, abstractmethod# 定义一个支付接口(抽象基类)
class IPayment(ABC):@abstractmethoddef pay(self, amount):"""支付方法,所有支付方式都必须实现"""pass# 具体实现:信用卡支付
class CreditCardPayment(IPayment):def pay(self, amount):print(f"Paid {amount} using Credit Card.")# 具体实现:PayPal 支付
class PayPalPayment(IPayment):def pay(self, amount):print(f"Paid {amount} using PayPal.")# 具体实现:比特币支付
class BitcoinPayment(IPayment):def pay(self, amount):print(f"Paid {amount} using Bitcoin.")# 客户端代码,使用支付系统
def process_payment(payment_method, amount):payment_method.pay(amount)# 测试代码
credit_card = CreditCardPayment()
paypal = PayPalPayment()
bitcoin = BitcoinPayment()# 使用不同的支付方式处理支付
process_payment(credit_card, 100)
process_payment(paypal, 200)
process_payment(bitcoin, 300)

这种实现关系可以很容易地为系统添加新的实现方式(如支持新的支付方式),而不需要修改现有代码,新增的实现类只需要实现接口即可,完全可以独立于其他代码进行开发,将客户端代码与具体实现解耦来提高系统的可维护性,如果不使用实现关系,直接让 process_payment 依赖于具体的支付类,那么就会出现下面这种不停维护客户端代码的情况

def process_payment(payment_method, amount):if isinstance(payment_method, CreditCardPayment):payment_method.pay(amount)elif isinstance(payment_method, PayPalPayment):payment_method.pay(amount)elif isinstance(payment_method, BitcoinPayment):payment_method.pay(amount)# 如果以后新增一种支付方式,还要在这里加新的条件分支

2.2.6 依赖

  • 依赖Dependency:表示一个元素对另一个元素的使用或依赖,但这种关系不像关联或继承那么强,它表示类之间更松散的耦合连接,典型场景是类的方法依赖于另一个类的对象作为参数或返回。 用带普通箭头的虚线表示,箭头指向被依赖者
    在这里插入图片描述

依赖举例:办公室工作人员会使用打印机打印东西,OfficeWorker 依赖 Printer,但并没有保存 Printer 的实例,它只在需要打印时使用Printer

class Printer:def print_document(self, document):print(f"Printing: {document}")class OfficeWorker:def __init__(self, name):self.name = namedef do_work(self, document, printer):printer.print_document(document)

使用依赖Usage Denpency是依赖的一种特定形式,表示一个类(client)利用或依赖另一个类(server)来执行某些任务或访问某些功能。client类依赖于server类提供的服务,但不拥有或创建其实例,上面的打印机例子也是一种使用依赖,此处不再细分描述

2.3 类图的作用

  • 建模类结构:类图通过表示类及其属性、方法和关系,帮助对系统结构进行建模,提供了系统架构的清晰而有条理的视图
  • 理解关系:类图描绘了类之间的关系,例如关联、聚合、组合、继承和依赖关系,有助于开发设计等人员了解系统结构
  • 实施蓝图:类图是软件实施的蓝图,通过说明类、它们的属性、方法及其之间的关系来指导开发人员编写代码
  • 代码生成:一些软件开发工具和框架支持从类图生成代码,开发人员可以从可视化表示中生成大量代码,从而减少手动错误的可能性并节省开发时间
  • 识别抽象和封装:类图能识别抽象以及在类中封装数据和行为,支持面向对象设计的原则,例如模块化和信息隐藏

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/53716.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用 Watchdog 实现 Python 程序的自动重载

在开发 Python 程序时,特别是在开发图形用户界面(GUI)应用时,我们经常需要频繁修改代码并查看效果。每次修改后手动重启程序既耗时又繁琐。本文将介绍如何使用 Watchdog 库来实现 Python 程序的自动重载,大大提高开发效率。 什么是 Watchdog? Watchdog 是一个 Python 库…

大数据新视界 --大数据大厂之Flink强势崛起:大数据新视界的璀璨明珠

💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

力扣---80. 删除有序数组中的重复项 II

给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。 不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。 说明&…

electron react离线使用monaco-editor

1.安装monaco-editor/react和monaco-editor pnpm i monaco-editor/react pnpm i monaco-editor 2.引入并做monaco-editor离线配置 import Editor, { DiffEditor, useMonaco, loader } from monaco-editor/react import * as monaco from monaco-editor import editorWorke…

软考 -- 软件设计师 -- 二轮复习(3) -- 数据结构(持续更新)

软考 – 软件设计师 – 二轮复习(3) – 数据结构(持续更新) 文章目录 软考 -- 软件设计师 -- 二轮复习(3) -- 数据结构(持续更新)前言一、时间、空间复杂度二、递归式时间复杂度三、线性表四、栈五、栈和队列六、串七、朴素模式匹配八、KMP模式匹配九、数组十、矩阵十一、树、二…

C#基础(10)变长参数和参数默认值

前言 作为函数的补充知识点,我们已经学习了ref和out,接下来两节我们继续来讲函数相关的内容。本节则讲解变长参数和参数默认值。 函数语法 关键字:params public void PrintNumbers(params int[] numbers) {for 相关逻辑 } 注意 params…

MySql批量迁移数据库

导出数据库 将指定数据库实例(MYSQL_HOST、MYSQL_PORT、MYSQL_USER、MYSQL_PASSWORD)中的所有数据库(表结构、数据)导出到指定目录(BACKUP_DIR)下的多个单独的SQL脚本,每个SQL脚本名称即为数据…

HarmonyOS开发实战( Beta5.0)自定义装饰器实践规范

介绍 本示例介绍通过自定义装饰器在自定义组件中自动添加inspector (布局回调)方法并进行调用。 效果图预览 不涉及 使用说明 在自定义组件上添加自定义装饰器CallbackObserver,并根据参数设置对应的方法名和需要绑定的组件的ID。编译工程,可以根据…

四款音频剪辑软件免费使用,你更pick哪一个?

视频剪辑知随着软件的不断更新,入门门槛和操作难度也随之变得越来越低,但是依然有不少人不知道剪辑视频要用什么工具,作为一个视频剪辑爱好者,我尝试过不少编辑软件,今天就来跟大家分享一下四款视频剪辑软件在实际使用…

adb devices不显示连接设备怎么解决

adb devices不显示设备,首先用老办法检查。假如是显示adb这个命令不认识,那就是系统路径问题。假如能认识adb这个命令,那就检查一下手机有没有开usb调试。 但是我遇到了更奇怪的问题:我把网上的攻略都试了一遍,设备驱…

通用四期ARM架构银河麒麟桌面操作系统V10【安装、配置FTP客户端】

一、操作环境 服务端:银河麒麟桌面操作系统V10SP1 客户端:银河麒麟桌面操作系统V10SP1 二、服务端配置 注:以下命令均在终端执行 鼠标点击桌面右键,选择打开终端 操作步骤: 1、安装vsftpd软件:如果提…

深入理解TCP三次握手

在网络通信中,TCP(Transmission Control Protocol,传输控制协议)是一个可靠的、面向连接的协议,它保证了数据包的顺序和完整性。为了建立一个稳定的连接,TCP 使用了一个被称为 三次握手(Three-W…

滑动窗口(1)_长度最小的子数组

个人主页:C忠实粉丝 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C忠实粉丝 原创 滑动窗口(1)_长度最小的子数组 收录于专栏【经典算法练习】 本专栏旨在分享学习C的一点学习笔记,欢迎大家在评论区交流讨论💌 目录 1. …

一款高效、简洁的帧动画生成工具

在现代网页设计和移动应用开发中,帧动画是一种常见的动画实现方式,它通过连续显示一系列静态图片来模拟动画效果。然而,手动创建和管理这些帧动画图片不仅耗时费力,而且效率低下。为此,gka 应运而生,它是一…

Java学习Day41:骑龙救!(springMVC)

springMVC与sevlet都是对应表现层web的,但是越复杂的项目使用SpringMVC越方便 基于Java实现MVC模型的轻量级web框架 目标: 小案例: 1.导入依赖 spring-context: 提供 Spring 框架的核心功能,如依赖注入、事件发布和其他应用上…

利用分布式锁在ASP.NET Core中实现防抖

前言 在 Web 应用开发过程中,防抖(Debounce) 是确保同一操作在短时间内不会被重复触发的一种有效手段。常见的场景包括防止用户在短时间内重复提交表单,或者避免多次点击按钮导致后台服务执行多次相同的操作。无论在单机环境中&a…

人工智能如何改变我们的工作方式

最近,我突然发现,人工智能正在悄悄地改变我们每天的工作方式。可能你和我一样,一开始并没怎么注意到这些变化,直到有一天,我才恍然大悟——原来我们已经不知不觉中被AI“包围”了!它正在一点一点地改变着我…

无人机之伯努利定律

无人机的伯努利定律是解释无人机飞行原理的关键理论之一,它主要阐述了流体(如空气)在流动过程中速度与压力之间的关系。以下是对无人机伯努利定律的详细解释: 一、伯努利定律的基本原理 伯努利定律是流体力学中的一个基本原理&am…

JavaScript知识点1

目录 1.JavaScript中常用的数组方法有哪些? 2.JavaScript的同源策略? 3.JavaScript中的 NaN 是什么? 4.JavaScript中的split、slice、splice函数区别? 1.JavaScript中常用的数组方法有哪些? 在 JavaScript 中&…

NEEP-EN2-2020-Text4

英二-2020-Text 4 摘自新闻周刊《Newsweek》2019年6月的文章《Gen Zs are Anxious, Entrepreneurial and Determined to Avoid Their Predecessor’s Mistakes》。 以下为个人解析,非官方公开标准资料,可能有误,仅供参考。(单词解…