UML中类图的介绍与使用

简介: 类图是 UML 中用于展示系统静态结构的重要工具,包括类、接口及其关系。类图有助于系统可视化、团队沟通、发现设计问题、文档化系统和辅助开发工具。类图的三大元素是类、接口和关系,其中关系又细分为关联、聚合、组合、继承、实现和依赖。类图在设计模式学习和实际开发中非常重要,许多现代 IDE 都支持从类图生成代码或从代码生成类图。

类图

UML(Unified Modeling Language,统一建模语言)中的类图(Class Diagram)是一种静态结构图,它用于展示系统中的类(class)、接口(interface)、协作(collaboration)以及它们之间的静态结构和关系。

画类图的好处

类图是面向对象设计中的重要工具,它的主要优点包括:

  1. 提供系统的视觉表示:类图提供了系统的静态视图,可以清晰地展示系统中的类以及它们之间的关系。这对于理解和解释系统的结构和行为非常有帮助。
  2. 促进团队之间的沟通:类图是一种通用的语言,可以被所有的开发人员理解。通过类图,团队成员可以更好地理解系统的设计,并在设计的基础上进行讨论和改进。
  3. 帮助发现设计问题:通过创建类图,我们可以在早期发现设计上的问题,比如类之间的耦合过度,或者职责分配不清等问题。这可以在实际编码之前就避免这些问题,提高开发效率。
  4. 文档化系统:类图可以作为系统的一部分文档,为未来的维护和开发提供参考。通过查看类图,新的开发人员可以更快地理解系统的结构和行为。
  5. 辅助软件开发工具:许多现代的软件开发工具,如IDE,都支持从类图生成代码,或者从代码生成类图。这可以帮助开发人员更快地进行开发,并保持代码和设计的一致性。

在学习设计模式的过程中,一定要自己画类图,这样可以更好地理解设计模式的实现原理,并且在实际开发中能够更好地应用设计模式。

类图三元素

  1. 类(Class):类是类图的主要元素,通常用一个矩形表示。矩形分为三个部分:上部是类名,中部是属性,下部是方法。
  2. 接口(Interface):接口在类图中以一个带有《接口名》标签的矩形表示,或者用一个带有接口名的圆柱表示。
  3. 关系:类图中的关系包括关联(Association)、聚合(Aggregation)、组合(Composition)、继承(Inheritance)、实现(Implementation)和依赖(Dependency)。

六种关系

解释

  • 关联(Association):关联是类与类之间的一种链接,表示一个类知道另一个类的属性和方法。关联可以是单向的,也可以是双向的。关联在类图中以实线和箭头表示。
  • 聚合(Aggregation):聚合是一种特殊的关联,表示"整体和部分"的关系,部分可以脱离整体而独立存在。聚合在类图中以空心菱形和实线表示。
  • 组合(Composition):组合也是一种特殊的关联,表示"整体和部分"的关系,但部分不能脱离整体而独立存在。组合在类图中以实心菱形和实线表示。
  • 继承(Inheritance):继承表示一个类(子类)继承另一个类(父类)的属性和方法。继承在类图中以空心三角形和实线表示。
  • 实现(Implementation):实现表示一个类实现一个接口的方法。实现在类图中以空心三角形和虚线表示。
  • 依赖(Dependency):依赖表示一个类的实例在方法内部使用到另一个类的实例。依赖在类图中以虚线和箭头表示。

单个说明

1. 关联(Association)

代码

class Car {
   private Engine engine;
   public void start() {
       engine.start();
   }
}

class Engine {
   public void start() {
       // 启动发动机
   }
}

类图

在这个例子中,Car类与Engine类之间存在关联关系。Car类包含一个Engine类型的成员变量engine,并且在start方法中使用了enginestart方法。

注意: 在这个例子中,Engine类是一个独立的类,它与Car类没有直接的关联关系。

2. 聚合(Aggregation)

代码

class School {
   private List<Student> students;
   public void addStudent(Student student) {
       students.add(student);
   }
}

class Student {
   // 学生的属性和方法
}

类图

在这个例子中,School类与Student类之间存在聚合关系。School类包含一个List<Student>类型的成员变量students,并且提供了一个addStudent方法用于添加学生。

注意: 在这个例子中,Student类是一个独立的类,它与School类没有直接的关联关系。

3. 组合(Composition)

代码

class House {
   private List<Room> rooms;
   public House(List<Room> rooms) {
       this.rooms = rooms;
   }
}

class Room {
   // 房间的属性和方法
}

类图

在这个例子中,House类与Room类之间存在组合关系。House类包含一个List<Room>类型的成员变量rooms,并且在构造函数中初始化rooms

注意: 在这个例子中,Room类是一个独立的类,它与House类没有直接的关联关系。

4. 继承(Inheritance)

代码

class Animal {
   public void eat() {
       // 动物吃东西
   }
}

class Dog extends Animal {
   public void bark() {
       // 狗叫
   }
}

类图

在这个例子中,Dog类继承自Animal类,因此Dog类具有Animal类的eat方法。

注意: 在这个例子中,Dog类继承自Animal类,因此Dog类具有Animal类的eat方法。

5. 实现(Implementation)

代码

interface Drawable {
   public void draw();
}

class Circle implements Drawable {
   public void draw() {
       // 绘制圆形
   }
}

类图

在这个例子中,Circle类实现了Drawable接口,因此Circle类必须实现draw方法。

注意: 在这个例子中,Circle类实现了Drawable接口,因此Circle类必须实现draw方法。

6. 依赖(Dependency)

代码

class Car {
   private Engine engine;
   public void start() {
       engine.start();
   }
}

class Engine {
   public void start() {
       // 启动发动机
   }
}

类图

在这个例子中,Car类与Engine类之间存在依赖关系。Car类包含一个Engine类型的成员变量engine,并且在start方法中使用了enginestart方法。

注意: 在这个例子中,Engine类是一个独立的类,它与Car类没有直接的关联关系。

汇总说明

代码

c++

// B.h
class B {
public:
   B() { std::cout << "B created" << std::endl; }
   ~B() { std::cout << "B destroyed" << std::endl; }
   void display() { std::cout << "Displaying B" << std::endl; }
};

// C.h
class C {
public:
   C() { std::cout << "C created" << std::endl; }
   ~C() { std::cout << "C destroyed" << std::endl; }
   void display() { std::cout << "Displaying C" << std::endl; }
};

// D.h
#include "A.h"

class D {
   A* a_;
public:
   D(A* a) : a_(a) { std::cout << "D created" << std::endl; }
   ~D() { std::cout << "D destroyed" << std::endl; }
   void display() { std::cout << "Displaying D" << std::endl; }
};

// E.h
class F {
public:
   virtual void display() { std::cout << "Displaying F" << std::endl; }
};

class E : public F {
public:
   void display() override { std::cout << "Displaying E" << std::endl; }
};

// I.h
class I {
public:
   virtual void method() = 0;
};

// Implementation.h
#include "I.h"

class Implementation : public I {
public:
   void method() override { std::cout << "Implementation of method" << std::endl; }
};

// A.h
#include "B.h"
#include "C.h"
#include "D.h"

class A {
private:
   B* bPtr; // 关联:A不拥有B
   C* cPtr; // 聚合:A拥有C
   D* dPtr; // 组合:A拥有D

public:
   A() : dPtr(new D(this)) {
       cPtr = new C(); // A创建C,显示A拥有C
       bPtr = new B(); // A创建B,但A不拥有B
   }
   ~A() {
       delete cPtr; // A销毁时,销毁C,因为A拥有C
       delete dPtr; // A销毁时,销毁D,因为A拥有D
       // 不销毁bPtr,因为A不拥有B
   }

   void display() {
       std::cout << "Displaying A" << std::endl;
       bPtr->display(); // 使用关联对象B
       cPtr->display(); // 使用聚合对象C
       dPtr->display(); // 使用组合对象D
   }
};

// main.cpp
#include "A.h"

int main() {
   A a;
   a.display();
   return 0;
}

c#

// B.cs
public class B {
   public B() { Console.WriteLine("B created"); }
   public ~B() { Console.WriteLine("B destroyed"); }
   public void Display() { Console.WriteLine("Displaying B"); }
}

// C.cs
public class C {
   public C() { Console.WriteLine("C created"); }
   public ~C() { Console.WriteLine("C destroyed"); }
   public void Display() { Console.WriteLine("Displaying C"); }
}

// D.cs
public class D {
   private A a_;
   public D(A a) {
       a_ = a;
       Console.WriteLine("D created");
   }
   public ~D() { Console.WriteLine("D destroyed"); }
   public void Display() { Console.WriteLine("Displaying D"); }
}

// E.cs
public class F {
   public virtual void Display() { Console.WriteLine("Displaying F"); }
}

public class E : F {
   public override void Display() { Console.WriteLine("Displaying E"); }
}

// I.cs
public interface I {
   void Method();
}

// Implementation.cs
public class Implementation : I {
   public void Method() { Console.WriteLine("Implementation of method"); }
}

// A.cs
public class A {
   private B bPtr; // 关联:A不拥有B
   private C cPtr; // 聚合:A拥有C
   private D dPtr; // 组合:A拥有D

   public A() {
       dPtr = new D(this);
       cPtr = new C();
       bPtr = new B();
   }

   ~A() {
       cPtr = null;
       dPtr = null;
       // 不销毁bPtr,因为A不拥有B
   }

   public void Display() {
       Console.WriteLine("Displaying A");
       bPtr.Display(); // 使用关联对象B
       cPtr.Display(); // 使用聚合对象C
       dPtr.Display(); // 使用组合对象D
   }
}

// Program.cs
using System;

class Program {
   static void Main() {
       A a = new A();
       a.Display();
   }
}

类图

在上面的示例中:

  • A 类与 B 类之间有一个使用关系(uses),表示 A 类使用了 B 类的对象。
  • A 类与 C 类之间有一个聚合关系(aggregates),表示 A 类聚合了 C 类的对象,但 C 类的对象可以独立于 A 类存在。
  • A 类与 D 类之间有一个组合关系(composes),表示 A 类组合了 D 类的对象,D 类的对象的生命周期依赖于 A 类。
  • A 类与 E 类之间有一个使用关系(uses),表示 A 类使用了 E 类的对象。
  • E 类继承自 F 类(extends),表示 E 类继承了 F 类的属性和方法。
  • Implementation 类实现了 I 接口(implements),表示 Implementation 类实现了 I 接口中定义的方法。

画类图工具推荐

其一:在线工具(processon)

网址:https://www.processon.com/

登陆软件后自己创建文件即可开始画图,非会员创建文件有数量限制,但对于类图绘制来说,一个文件就可以,效果如下:

其二:markdown画图

在支持mermaid的markdown编辑器中即可实现类图的绘制,代码及效果如下:

classDiagram
   Factory --|> ProductA: createProduct("A")
   Factory --|> ProductB: createProduct("B")
   class Factory{
       +createProduct(type: String): Product
   }
   class ProductA{
       +operation(): void
   }
   class ProductB{
       +operation(): void
   }
   ProductA --|> Product
   ProductB --|> Product
   class Product{
       +operation(): void
   }


目录
相关文章
|
6天前
|
存储 运维 安全
云上金融量化策略回测方案与最佳实践
2024年11月29日,阿里云在上海举办金融量化策略回测Workshop,汇聚多位行业专家,围绕量化投资的最佳实践、数据隐私安全、量化策略回测方案等议题进行深入探讨。活动特别设计了动手实践环节,帮助参会者亲身体验阿里云产品功能,涵盖EHPC量化回测和Argo Workflows量化回测两大主题,旨在提升量化投研效率与安全性。
云上金融量化策略回测方案与最佳实践
|
8天前
|
人工智能 自然语言处理 前端开发
从0开始打造一款APP:前端+搭建本机服务,定制暖冬卫衣先到先得
通义灵码携手科技博主@玺哥超carry 打造全网第一个完整的、面向普通人的自然语言编程教程。完全使用 AI,再配合简单易懂的方法,只要你会打字,就能真正做出一个完整的应用。
8003 19
|
11天前
|
Cloud Native Apache 流计算
资料合集|Flink Forward Asia 2024 上海站
Apache Flink 年度技术盛会聚焦“回顾过去,展望未来”,涵盖流式湖仓、流批一体、Data+AI 等八大核心议题,近百家厂商参与,深入探讨前沿技术发展。小松鼠为大家整理了 FFA 2024 演讲 PPT ,可在线阅读和下载。
4356 10
资料合集|Flink Forward Asia 2024 上海站
|
19天前
|
人工智能 自动驾驶 大数据
预告 | 阿里云邀您参加2024中国生成式AI大会上海站,马上报名
大会以“智能跃进 创造无限”为主题,设置主会场峰会、分会场研讨会及展览区,聚焦大模型、AI Infra等热点议题。阿里云智算集群产品解决方案负责人丛培岩将出席并发表《高性能智算集群设计思考与实践》主题演讲。观众报名现已开放。
|
12天前
|
自然语言处理 数据可视化 API
Qwen系列模型+GraphRAG/LightRAG/Kotaemon从0开始构建中医方剂大模型知识图谱问答
本文详细记录了作者在短时间内尝试构建中医药知识图谱的过程,涵盖了GraphRAG、LightRAG和Kotaemon三种图RAG架构的对比与应用。通过实际操作,作者不仅展示了如何利用这些工具构建知识图谱,还指出了每种工具的优势和局限性。尽管初步构建的知识图谱在数据处理、实体识别和关系抽取等方面存在不足,但为后续的优化和改进提供了宝贵的经验和方向。此外,文章强调了知识图谱构建不仅仅是技术问题,还需要深入整合领域知识和满足用户需求,体现了跨学科合作的重要性。
|
7天前
|
人工智能 容器
三句话开发一个刮刮乐小游戏!暖ta一整个冬天!
本文介绍了如何利用千问开发一款情侣刮刮乐小游戏,通过三步简单指令实现从单个功能到整体框架,再到多端优化的过程,旨在为生活增添乐趣,促进情感交流。在线体验地址已提供,鼓励读者动手尝试,探索编程与AI结合的无限可能。
三句话开发一个刮刮乐小游戏!暖ta一整个冬天!
|
1月前
|
存储 人工智能 弹性计算
阿里云弹性计算_加速计算专场精华概览 | 2024云栖大会回顾
2024年9月19-21日,2024云栖大会在杭州云栖小镇举行,阿里云智能集团资深技术专家、异构计算产品技术负责人王超等多位产品、技术专家,共同带来了题为《AI Infra的前沿技术与应用实践》的专场session。本次专场重点介绍了阿里云AI Infra 产品架构与技术能力,及用户如何使用阿里云灵骏产品进行AI大模型开发、训练和应用。围绕当下大模型训练和推理的技术难点,专家们分享了如何在阿里云上实现稳定、高效、经济的大模型训练,并通过多个客户案例展示了云上大模型训练的显著优势。
104580 10
|
7天前
|
消息中间件 人工智能 运维
12月更文特别场——寻找用云高手,分享云&AI实践
我们寻找你,用云高手,欢迎分享你的真知灼见!
637 39
|
5天前
|
弹性计算 运维 监控
阿里云云服务诊断工具:合作伙伴架构师的深度洞察与优化建议
作为阿里云的合作伙伴架构师,我深入体验了其云服务诊断工具,该工具通过实时监控与历史趋势分析,自动化检查并提供详细的诊断报告,极大提升了运维效率和系统稳定性,特别在处理ECS实例资源不可用等问题时表现突出。此外,它支持预防性维护,帮助识别潜在问题,减少业务中断。尽管如此,仍建议增强诊断效能、扩大云产品覆盖范围、提供自定义诊断选项、加强教育与培训资源、集成第三方工具,以进一步提升用户体验。
626 243
|
1天前
|
弹性计算 运维 监控
云服务测评 | 基于云服务诊断全方位监管云产品
本文介绍了阿里云的云服务诊断功能,包括健康状态和诊断两大核心功能。作者通过个人账号体验了该服务,指出其在监控云资源状态和快速排查异常方面的优势,同时也提出了一些改进建议,如增加告警配置入口和扩大诊断范围等。