UML 关系详解

依赖(Dependency)

  • 含义:一个类的变化会影响到另一个类,但反之不一定。这是一种"使用"关系,通常是临时的、较弱的。
  • 典型场景 :一个类作为另一个类方法的局部变量方法参数 ,或调用静态方法
  • UML表示 :带箭头的虚线,箭头指向被依赖的类(即"使用者"指向"被使用者")。
  • 代码示例
java 复制代码
// 动物类 依赖于 水类(喝水方法需要用水对象作为参数)
public class Animal {
    public void drink(Water w) { // 作为方法参数
        System.out.println(w.getName());
    }
}

关联(Association)

  • 含义:一个对象知道另一个对象的长期存在。这是一种"拥有"或"知道"的关系,比依赖更强、更持久。
  • 典型场景:一个类以"成员变量(属性)"的形式保存对另一个类的引用。
  • UML表示实线 ,通常带箭头指向被关联的类(双向关联可以没有箭头或有双向箭头)。可以标注多重性(如 1, 0.., 1.. 等)。
  • 代码示例
java 复制代码
public class Person
{
    private Book _book;  // 单向关联
    
    public Person(Book book)
    {
        _book = book;
    }
    
    public void Read()
    {
        Console.WriteLine($"Reading: {_book.Title}");
    }
}

public class Book
{
    public string Title { get; set; }
    
    public Book(string title)
    {
        Title = title;
    }
}

聚合(Aggregation)组合(Composition) 确实都是关联关系(Association) 的特殊形式。

聚合(Aggregation)

特点 :是整体与部分 的关系,且部分可以离开整体而单独存在(如"汽车"和"轮胎")。

场景:汽车有轮子,但轮子可以拆下来装到别的车上。

UML表示带空心菱形的实线,菱形指向整体。

cs 复制代码
public class Car
{
    public string Model { get; set; }
    private List<Wheel> _wheels = new List<Wheel>();  // 聚合
    
    public void AddWheel(Wheel wheel)
    {
        _wheels.Add(wheel);
        wheel.SetCar(this);
    }
    
    public void RemoveWheel(Wheel wheel)
    {
        _wheels.Remove(wheel);
        wheel.RemoveCar();
    }
}

public class Wheel
{
    public string Brand { get; set; }
    public int Size { get; set; }
    private Car _car;  // 可选的反向引用
    
    public void SetCar(Car car) => _car = car;
    public void RemoveCar() => _car = null;
}

组合(Composition)

特点 :是整体与部分 的关系,但部分不能离开整体而单独存在。同生同灭。

场景:如公司和部门是组合关系,没有公司就不存在部门。

**UML表示:**带实心(黑色实心:要死一起死,良心是黑的)菱形的实线,菱形指向整体。

cs 复制代码
public class Order
{
    public int OrderId { get; set; }
    private List<OrderItem> _items = new List<OrderItem>();  // 组合
    
    public void AddItem(string productName, int quantity, decimal price)
    {
        // OrderItem 的创建和销毁完全由 Order 控制
        var item = new OrderItem(productName, quantity, price);
        _items.Add(item);
    }
    
    public decimal GetTotal()
    {
        return _items.Sum(i => i.GetSubtotal());
    }
    
    ~Order()
    {
        // 订单销毁时,OrderItem 也会被销毁(GC 回收)
        Console.WriteLine($"Order {OrderId} disposed, items also disposed");
    }
}

public class OrderItem
{
    public string ProductName { get; set; }
    public int Quantity { get; set; }
    public decimal UnitPrice { get; set; }
    
    public OrderItem(string productName, int quantity, decimal price)
    {
        ProductName = productName;
        Quantity = quantity;
        UnitPrice = price;
    }
    
    public decimal GetSubtotal() => Quantity * UnitPrice;
}

泛化(Generalization)

  • 含义 :即面向对象的继承关系。子类继承父类的属性和方法。
  • 典型场景:普通类继承普通类,或抽象类继承抽象类。
  • UML表示 :空心三角形 + 实线,空心三角形指向父类。
  • 代码示例
java 复制代码
// 父类
public class Animal {
    public void eat() {}
}
// 子类 泛化 父类
public class Dog extends Animal {
    public void bark() {}
}

实现(Realization)

  • 含义:类实现接口。类遵循接口定义的契约,实现其所有方法。
  • 典型场景:一个普通类实现一个或多个接口。
  • UML表示 :空心三角形 + 虚线,空心三角形指向接口。
  • 代码示例
java 复制代码
// 接口
public interface Flyable {
    void fly();
}
// 鸟类 实现 飞行接口
public class Bird implements Flyable {
    @Override
    public void fly() {
        System.out.println("Bird flying...");
    }
}

关系强弱排序

在UML(统一建模语言)中,这六种关系(依赖、关联、聚合、组合、泛化、实现)从语义强度(即类与类之间联系的紧密程度、耦合度高低、依赖性大小)来看,通常的排序由弱到强如下:

强弱排序(从最弱到最强)

依赖 < 关联 < 聚合 < 组合 < 实现 < 泛化

另一种常见视角 (从代码修改的影响范围看):泛化实现 的耦合度最高,因为它们直接决定了类的结构和契约;而组合虽然整体-部分关系极强,但往往封装在内部,对外部的耦合扩散有时弱于继承。

  1. 依赖(最弱)
  • 特点:仅仅是临时性的"使用"关系。一个类的变化可能会影响另一个类,但反过来不成立。
  • 典型形式:局部变量、方法参数、静态方法调用。
  • 强度理由:被依赖者并不作为使用者的长期状态存在,生命周期短暂。
  1. 关联(弱)
  • 特点:长期持有的"知道/拥有"关系。一个类以成员变量形式引用另一个类。
  • 强度理由:比依赖强,因为被关联者是类的一部分状态,但双方生命周期独立,可以单独存在。
  1. 聚合(中弱)
  • 特点:特殊的关联,表示"整体-部分"关系,但部分可以脱离整体独立存在。
  • 例子:汽车(整体)与轮胎(部分)。轮胎拆下来仍可装到别的车上。
  • 强度理由:比普通关联强,因为有明确的整体-部分语义,但生命周期独立。
  1. 组合(中强)
  • 特点:更强的"整体-部分"关系,部分的生命周期由整体控制,不能单独存在。
  • 例子:人(整体)与心脏(部分)。心脏脱离人体即失去意义。
  • 强度理由:比聚合强,因为整体负责创建和销毁部分,耦合度更高。
5. 实现(强)
  • 特点:类与接口之间的契约关系。实现类必须遵守接口的全部约定。
  • 强度理由:实现类依赖于接口定义的稳定契约,如果接口改变,所有实现类都受影响。比起组合,它对系统架构的约束更广泛。
6. 泛化(最强)
  • 特点:继承关系,子类完全依赖于父类的实现细节(即便使用里氏替换原则,也存在白盒复用)。
  • 强度理由 :这是最强的耦合关系。父类的一个方法修改,可能波及所有子类;且子类无法分离对父类的依赖。因此被公认强度最高
  • 设计原则警示 :面向对象设计原则中提倡"组合优于继承 "(Composition over Inheritance),正是因为泛化(继承)的耦合度太强
相关推荐
疯狂打码的少年8 天前
UML类图究竟是什么?—— 软件开发中的“建筑蓝图”
uml
rolt8 天前
[幻灯片]分析设计高阶-02结构(2)-202604更新
ddd·架构师·uml·ooad
a里啊里啊10 天前
软考-软件评测师:知识点整理(七)——软件工程
设计模式·软件工程·软考·uml·结构化开发·软件评测师·软件模型
Warren2Lynch11 天前
[特殊字符]️ 综合指南:结合使用 C4 模型与 UML
uml·c4
Ting.~11 天前
软件设计师备考笔记【day2】-UML 图解 | 面向对象 | 设计模式
笔记·设计模式·uml
清钟沁桐14 天前
编程设计之三 -- UML
uml
choke23314 天前
深度分析系统建模:从UML基础到类图和对象图的实际应用
大数据·软件工程·uml
黄昏回响16 天前
UML与SysML深度解析:从软件工程到系统工程的建模语言进化之路
程序人生·软件工程·uml·改行学it
雪碧聊技术17 天前
UML相关知识点精讲
uml