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),正是因为泛化(继承)的耦合度太强
相关推荐
吴声子夜歌2 小时前
PlantUML——序列图
uml·plantuml·序列图
吴声子夜歌4 小时前
PlantUML——活动图
uml·plantuml·活动图
吴声子夜歌1 天前
PlantUML——类图(一)
uml
吴声子夜歌1 天前
PlantUML——类图(二)
uml·plantuml·类图
吴声子夜歌1 天前
PlantUML——对象图
uml·plantuml·对象图
吴声子夜歌2 天前
PlantUML——用例图
uml·plantuml
rolt4 天前
PlantUML描述《分析模式》第4章企业财务观察(1)
产品经理·架构师·uml·系统工程
KobeSacre5 天前
UML 学习
学习·uml
hssfscv7 天前
软件设计师2021上、下上午题错题解析+2022上、下下午题训练5道 练习真题训练16
笔记·设计模式·uml
_codemonster9 天前
UML静态图之构件图(也叫组件图)详解
uml