00-设计模式系列之---30秒掌握UML类图核心要点

118 阅读6分钟

本设计模式系列通过UML类图基础、设计原则、设计模式详解和项目实战四个阶段,循序渐进地帮助读者掌握设计模式的核心思想与实际应用。从理论到实践,结合丰富的案例和主流框架分析,全面提升开发者的代码设计能力和软件开发水平。

我们在阅读开源项目时,总是希望能比较高效的整理清楚项目中的各个类之间的关系,那么有没有相应的工具能高效、简洁的表示清楚类关系呢?UML类图就是一个可以帮我们解决此类问题的工具或者方法。

1. 什么是类图?

  • 定义:UML类图是一种静态结构图,用于描述系统的类、属性、操作(方法)以及类之间的关系。
  • 核心价值:高效梳理代码结构,可视化类之间的交互,提升代码可读性和设计质量。
  • 适用场景:阅读开源项目、系统设计、团队协作沟通。

2. 类图应用场景

  • 开发阶段:设计系统架构,明确类职责。
  • 文档化:为开源项目提供可维护的文档。
  • 逆向工程:通过代码生成类图(如IDEA插件)。
  • 业务建模:用类图描述业务实体关系(如电商系统中的订单-商品)。

3. 类图的核心组成

元素符号/规则示例补充说明
类名首字母大写Animal抽象类名用斜体
接口<<interface>> + 接口名<<Flyable>>无属性,仅抽象方法
属性可见性 名称: 类型 = 默认值-name: String = "Unknown"成员变量
操作(方法)可见性 名称(参数:类型): 返回类型+fly(speed: int): void代表类提供的服务
可见性+ (public) - (private) # (protected) ~ (package)#age: int控制访问权限- +表示公共属性或操作;
  • -表示私有属性或操作;
  • #表示受保护的属性或操作;
  • 〜表示包属性或操作。 |

4. 类关系

六种核心关系对比

关系类型符号方向语义代码体现生命周期
继承◁━ 实线 + 空心三角子类 → 父类is-a(泛化)class Duck extends Bird独立
实现╌╌▷ 虚线 + 空心三角实现类 → 接口实现契约class Plane implements Flyable独立
关联──> 实线箭头持有类 → 被关联类长期引用关系成员变量 private Address address;独立
聚合◇━━ 实线 + 空心菱形部分类 ← 整体类has-a(弱拥有)class Team { List<Member> members; }部分可独立存在
组合◆━━ 实线 + 实心菱形部分类 ← 整体类contains-a(强拥有)class Car { Engine engine; }部分随整体销毁
依赖╌╌> 虚线箭头使用类 → 被依赖类临时使用局部变量/参数/返回值临时

关键区别

  • 聚合 vs 组合
    • 聚合:部分可独立存在(如教室学生,学生可离开教室)。
    • 组合:部分与整体共存亡(如公司部门,公司倒闭则部门消失)。
  • 关联 vs 依赖
    • 关联:长期持有对象引用(如用户拥有地址)。
    • 依赖:临时使用(如订单调用支付工具的方法)。

4.1. 继承(或泛化)

  • 表示一般与特殊的关系,是父类与子类之间的关系,是一种继承关系,是 is-a 的关系;
  • 继承关系采用空心三角形+实线来表示, 由派生类指向基类。

4.2. 实现

  • 是接口与实现类之间的关系。类实现了接口,类中的操作实现了接口中所声明的所有的抽象操作;
  • 实现接口采用空心三角形+虚线来表示,由类指向接口。

4.3. 关联

  • 是对象之间的一种引用关系,用于表示一类对象与另一类对象之间的联系;
  • 两个对等类之间的结构链接;
  • 关联关系采用实线箭头表示,箭头从使用类指向被关联的类。

4.4. 聚合

  • 表示一种弱的“拥有”关系,是整体和部分之间的关系,是 has-a 的关系;
  • 聚合关系是通过成员对象来实现的,其中成员对象是整体对象的一部分,但是成员对象可以脱离整体对象而独立存在;
  • 聚合关系采用空心菱形+实线表示,菱形端为整体对象。

4.5. 复合(或组合)

  • 表示一种强的“拥有”关系,体现了严格的部分和整体的关系,是contain-a的关系;
  • 整体对象和部分对象的声明周期一样,一旦整体对象不存在部分对象也将不存在,部分对象不能脱离整体对象而存在;
  • 复合关系采用实心菱形+实线表示,菱形端为整体对象。

4.6. 依赖

这种关系通常表现为局部变量方法返回值,方法的参数或者对某个方法的直接调用

  • 表示一种使用关系,是临时性的关联;
  • 依赖关系采用虚线箭头表示,箭头从使用类指向被依赖的类。

在 Java 类图中,依赖关系是一种比较常见的关系类型,表示一个类(或接口)使用了另一个类(或接口)的服务或功能,但并不持有对方的引用。下面列举了一些常见的依赖关系:

  1. 参数依赖

一个类的方法签名中包含另一个类的对象作为参数,表示这个类依赖于另一个类的实例。

public class ClassA {
    public void method(ClassB b) {
        // 使用 ClassB 的实例
    }
}

  1. 局部变量依赖

一个类中的方法内部定义了另一个类的对象作为局部变量,表示这个类依赖于另一个类的实例。

public class ClassA {
    public void method() {
        ClassB b = new ClassB();
        // 使用局部变量 b
    }
}

  1. 返回值依赖

一个类的方法返回了另一个类的对象,表示这个类依赖于另一个类的实例。

public class ClassA {
    public ClassB createObject() {
        return new ClassB();
    }
}

依赖关系是一种松耦合的关系,表示一个类对另一个类的使用,但并不是强关联,两者可以相互独立存在。

4.7. 类关系综合

5. 常见误区澄清

  • 箭头方向混淆:继承箭头指向父类,依赖箭头指向被依赖类
  • 组合误用:当部分可独立存在时,应用聚合而非组合。
  • 忽略可见性private属性不对外暴露,避免外部直接访问。