UML类图解析

UML类图解析

马草原 728 2023-06-03

UML类图解析

我们平时在做设计时经常需要画类图,画类图时候可能会有些许疑问,比如该用实线还是虚线?该用箭头还是三角形?聚合和组合有什么区别,什么时候用组合什么时候用聚合等等?
下面针对 UML 类之间的关系做一个总结,旨在搞清楚每个概念。

1、依赖(Dependency)

定义:一个类 A 的的某个成员函数的返回值、形参、局部变量或静态方法使用了另一个类 B,我们称 A 依赖 B

例子:假如我们现在有学生和电脑两个类,学生在运动时候可以不用电脑,但是在学习编程和打游戏时候需要电脑,我们说学生依赖电脑。学生离开了电脑只是编程和打游戏受到了影响,不会影响到其他活动,也就是说 A 依赖 B,但是没了 B 的情况下只会影响 A 的部分功能(学生没有电脑丝毫不影响唱歌、运动),不会导致 A 完全不可用

依赖关系使用虚线 + 箭头表示,如下
uml1

示例代码:

public class Computer {

    public void start() {
        System.out.println("Start Computer");
    }
    public void work() {
        System.out.println("Computer start working");
    }
}
public class Student {

    public void program(Computer computer) {
        computer.start();
        computer.work();
    }
    public void playGame() {
        Computer computer = new Computer();
        computer.start();
        computer.work();
    }
}

2、关联(Association)

定义:如果一个类 A 用一个类 B 的成员变量,A 和 B 就是关联关系

关联是比依赖更强的一种关系,关联的生命周期更长,往往和类的生命周期一样,二依赖的生命周期更短,和类中某一方法的生命周期一样

例子:学生可以不用电脑,但是既然称为学生一般情况下是不可以没有老师的,学生和老师就是关联关系

关联关系共有四种:单向关联、双向关联、自身关联、多为关联,使用实线 + 箭头表示(后面三种可以不用箭头)

2.1 单向关联

uml2

示例代码:

public class Teacher {

    public void teach() {
        
    }
}
public class Student {
	public Teacher teacher;
    public void study() {

    }
}

2.2 双向关联

uml3

2.3 自身关联

uml4

2.3 多维关联

uml5

3、聚合(Aggregation)

聚合用来表式集体与个体的关联关系关系。如一群学生聚合成了一个班级,使用空心菱形 + 实线表示,类图如下
uml7

聚合关系在代码上与关联关系表现一致,类 Student 将成为类 Classes 的成员变量

public class Student {

}
public class Classes {
	public Student student;
    public Classes(Student student) {
        this.student = student;
    }
}

聚合与组合的对比:

  • 聚合关系没有组合紧密

学生不会因为班级的解散而无法存在,聚合关系的类具有不同的生命周期;而人类如果没有心脏将无法存活,组合关系的类具有相同的生命周期。
这个从构造函数可以看出。聚合类的构造函数中包含另一个类的实例作为参数,因为构造函数中传递另一个类的实例,因此学生可以脱离班级体独立存在。组合类的构造函数包含另一个类的实例化。因为在构造函数中进行实例化,因此两者紧密耦合在一起,同生同灭,人类不能脱离心脏而存在。

  • 信息的封装性不同

在聚合关系中,客户端可以同时了解 Classes 类和 Student 类,因为他们是独立的。
在组合关系中,客户端只认识 Person 类,根本不知道 Heart 类的存在,因为心脏类被严密地封装在学生类中,理解聚合与组合的区别,主要在于聚合的成员可独立,组合的成员必须依赖于整体才有意义。

5、泛化(Generalization)

泛化是学术名称,通俗来讲,泛化指的是类与类之间的继承关系和类与接口之间的实现关系继承关系使用直线 + 空心三角形表示,接口实现使用虚线 + 空心三角形表示,类图结构如下:

5.1 继承

uml8

示例代码:

public class Person {
    private Heart heart;
    public void eat() {
        
    } 
}
public class Student extends Person {
    @Override
    public void eat() {
        super.eat();
    }
}

5.2 实现

uml9

示例代码:

public interface Walking {
    public void walk();
}
public class Student implements Walking {
    @Override
    public void walk() {

    }
}
public class Teacher implements Walking {
    @Override
    public void walk() {

    }
}

6、总结

依赖、关联、聚合、组合与泛化代表类与类之间的耦合度依次递增。依赖关系实际上是一种比较弱的关联,聚合是一种比较强的关联,组合是一种更强的关联,泛化则是一种最强的关联,所以笼统的来区分的话,实际上这五种关系都是关联关系。

  • 依赖关系比较好区分,它是耦合度最弱的一种,在编码中表现为类成员函数的局部变量、形参、返回值或对静态方法的调用
  • 关联、聚合与组合在编码形式上都以类成员变量的形式来表示,所以只给出一段代码我们很难判断出是关联、聚合还是组合关系,我们需要从上下文语境中来判别
  • 关联表示类之间存在联系,不存在集体与个体、个体与组成部分之间的关系
  • 聚合表示类之间存在集体与个体的关系。组合表示个体与组成部分之间的关系

uml10


第一层:动物依赖水和氧气
第二层:鸟类继承动物,鸟类拥有翅膀
第三层:大雁、企鹅、鸭子继承自鸟类,其中大雁会飞
第四层:大雁聚合成雁群,企鹅依赖气候。唐老鸭继承自鸭子,同时唐老鸭有说话的能力