1.依赖关系,在 UML 中,类与类之间的依赖关系通常表示为一个类使用另一个类,但不是强制绑定于这个类的长期存在。这种关系可以用 Java 代码中的方法参数、局部变量或返回类型等体现。下面是一个简单的示例,展示了类 A 依赖于类 B:
- 依赖关系:A 类依赖于 B 类,意味着 A 类在某些方法中使用了 B 类,但并不拥有 B 类的实例。用虚线实心箭头表示。
Java 代码示例
// B 类定义
public class B {
public void doSomething() {
System.out.println("B is doing something.");
}
}
// A 类定义,依赖于 B 类
public class A {
// A 类依赖 B 类作为方法参数
public void performTask(B b) {
b.doSomething(); // 调用 B 类的方法
}
public static void main(String[] args) {
B bInstance = new B(); // 创建 B 类的实例
A aInstance = new A(); // 创建 A 类的实例
aInstance.performTask(bInstance); // A 类通过依赖 B 类完成任务
}
}
- 依赖关系:在
A
类中,performTask()
方法接受一个B
类的实例作为参数,这就是 A 类对 B 类的依赖。 - 运行时依赖:
A
类并不长期持有B
类的实例,只是在调用performTask()
方法时需要使用B
类。
这种代码可以对应 UML 中的依赖关系箭头,从 A
类指向 B
类。
2.泛化关系,类与类之间的泛化(Generalization)关系表示一种继承关系,即子类(A 类)继承父类(B 类),从而获得父类的属性和方法。这个关系通常用一个带空心三角的箭头表示,箭头指向父类。
泛化关系:A 类是 B 类的子类,意味着 A 类继承了 B 类,A 类可以重用 B 类的属性和方法。用实线空心箭头表示。
// 父类 B
public class B {
public void doSomething() {
System.out.println("B is doing something.");
}
}
// 子类 A,继承自 B(泛化关系)
public class A extends B {
// A 类可以继承 B 类的方法,并且可以重写
@Override
public void doSomething() {
System.out.println("A is doing something differently.");
}
public static void main(String[] args) {
A aInstance = new A(); // 创建 A 类的实例
aInstance.doSomething(); // 调用 A 类重写的 doSomething() 方法
}
}
- 泛化关系:
A
类通过extends
关键字继承了B
类,这就是 Java 中的泛化关系。 - 方法重写:
A
类通过@Override
重写了B
类中的doSomething()
方法,表现为 A 类可以有不同的行为。 - 继承父类行为:
A
类可以访问和重用B
类中定义的其他方法和属性。
这个 Java 代码对应 UML 中的泛化关系,A
类继承 B
类,代表子类泛化父类。
3.关联关系,在 UML 中,类与类之间的关联关系表示一个类与另一个类之间的结构性关系,通常通过属性或字段来表示。关联关系与依赖关系不同,它表示一种更为紧密和长期的关系,通常一个类拥有另一个类的实例。
关联关系:A 类与 B 类有关联,意味着 A 类持有 B 类的引用,可以在其内部长期使用 B 类的实例。用直线连接。
// B 类定义
public class B {
private String name;
public B(String name) {
this.name = name;
}
public void displayInfo() {
System.out.println("B's name is: " + name);
}
}
// A 类定义,关联 B 类
public class A {
// A 类中包含一个 B 类的引用(关联关系)
private B bInstance;
// 构造函数接受 B 类的实例
public A(B bInstance) {
this.bInstance = bInstance;
}
public void useB() {
// 调用 B 类的方法
bInstance.displayInfo();
}
public static void main(String[] args) {
B b = new B("Example B"); // 创建 B 类的实例
A a = new A(b); // 创建 A 类并关联 B 类
a.useB(); // A 类通过关联关系使用 B 类的方法
}
}
- 关联关系:
A
类通过字段bInstance
持有B
类的引用,这是关联关系的表现。A
类的生命周期中可以持续访问和使用B
类的实例。 - 构造函数关联:在
A
类的构造函数中,将B
类的实例传递给A
类,表示建立了关联关系。 - 长期使用:
A
类可以长期保存B
类的实例引用,并通过useB()
方法调用B
类的功能。
这种代码模式对应 UML 中的关联关系,A 类与 B 类之间有一个双向或单向的结构性连接,通常表示为 A 持有 B 的引用。
4.聚合关系,是一种特殊的关联关系,表示一个类(整体)由另一个类(部分)组成,但部分可以独立于整体存在。这种关系在类图中通常用空心的菱形来表示。聚合关系说明整体类可以拥有部分类的实例,但这些部分的生命周期独立于整体类。
聚合关系:A 类聚合 B 类,意味着 A 类是整体,B 类是部分。即使 A 类不存在,B 类的实例仍然可以独立存在。
// B 类定义(部分)
public class B {
private String name;
public B(String name) {
this.name = name;
}
public void displayInfo() {
System.out.println("B's name is: " + name);
}
}
// A 类定义(整体),聚合 B 类
public class A {
// A 类包含 B 类的引用,但 B 类可以独立存在(聚合关系)
private B bInstance;
// A 类的构造函数可以接收 B 类的实例,建立聚合关系
public A(B bInstance) {
this.bInstance = bInstance;
}
public void useB() {
// 调用 B 类的方法
bInstance.displayInfo();
}
public static void main(String[] args) {
B b = new B("Part of A"); // 创建 B 类的实例,B 类可以独立存在
A a = new A(b); // A 类与 B 类建立聚合关系
a.useB(); // A 类通过聚合关系使用 B 类的方法
}
}
- 聚合关系:在
A
类中,bInstance
是B
类的引用,但B
类的实例是外部创建的,并传递给A
类。这表示B
类的实例可以在A
类之外独立存在。 - 生命周期独立:
B
类实例b
是在A
类之外创建的,意味着即使A
类对象消失了,B
类的实例依然可以继续存在。这正是聚合关系的特点。 - A 类使用 B 类:
A
类可以通过其bInstance
访问和使用B
类的功能。
这个 Java 代码展示了 UML 中聚合关系的实现:A 类通过参数传递方式与 B 类建立聚合,但 B 类的生命周期与 A 类是独立的。
5.组合关系,在 UML 中,组合关系(Composition)是一种更强的关联关系,表示一个类(整体)与另一个类(部分)之间的关系,但与聚合关系不同,组合关系中部分的生命周期依赖于整体。如果整体类被销毁,部分类也会被销毁。组合关系通常用实心菱形来表示。
组合关系:A 类组合 B 类,意味着 A 类拥有 B 类的实例,并且 B 类的生命周期依赖于 A 类。当 A 类对象被销毁时,B 类对象也必须被销毁。
// B 类定义(部分)
public class B {
private String name;
public B(String name) {
this.name = name;
}
public void displayInfo() {
System.out.println("B's name is: " + name);
}
}
// A 类定义(整体),组合 B 类
public class A {
// A 类创建和控制 B 类的实例(组合关系)
private B bInstance;
// 在 A 类的构造函数中,创建 B 类的实例
public A(String bName) {
this.bInstance = new B(bName); // A 类完全负责 B 类的生命周期
}
public void useB() {
// 调用 B 类的方法
bInstance.displayInfo();
}
public static void main(String[] args) {
A aInstance = new A("Part of A"); // 创建 A 类实例,A 类控制 B 类的创建
aInstance.useB(); // A 类通过组合关系使用 B 类的方法
// 当 aInstance 被销毁时,bInstance 也将被销毁
}
}
- 组合关系:在
A
类中,bInstance
是B
类的实例,并且由A
类的构造函数负责创建。这表示B
类的生命周期完全由A
类控制。 - 生命周期依赖:当
A
类的实例(aInstance
)被销毁时,B
类的实例(bInstance
)也会随之销毁。这正是组合关系的核心特征。 - 强依赖性:在组合关系中,
A
类不仅持有B
类的实例,而且负责其创建和销毁,B
类不能独立于A
类存在。
这个 Java 代码展示了 UML 中组合关系的实现:A
类负责 B
类实例的创建和销毁,表现出一种强依赖的组合关系。
6.实现关系,在 UML 中,实现关系(Realization)表示一个类(通常是接口或抽象类)定义了一组功能,而另一个类通过实现这些功能来满足该接口或抽象类的要求。实现关系通常用于接口和具体类之间,用虚线加空心三角表示。
实现关系:A 类实现 B 类,意味着 B 是接口或抽象类,定义了一组抽象方法,而 A 类提供了这些方法的具体实现。
// B 接口定义
public interface B {
// 接口方法,具体类必须实现
void doSomething();
}
// A 类实现 B 接口
public class A implements B {
// 实现 B 接口中的方法
@Override
public void doSomething() {
System.out.println("A is doing something.");
}
public static void main(String[] args) {
A aInstance = new A(); // 创建 A 类的实例
aInstance.doSomething(); // 调用实现的方法
}
}
- 接口实现:在第一个示例中,
B
是一个接口,定义了doSomething()
方法,A
类通过implements
关键字实现了该接口,并提供了方法的具体实现。 - 抽象类实现:在第二个示例中,
B
是一个抽象类,A
类通过继承B
抽象类并实现其中的抽象方法来实现其功能。 - 实现关系:在 UML 类图中,这种关系通常用虚线带空心三角形从实现类指向接口或抽象类。
这两个示例展示了 UML 实现关系的典型场景,A 类通过实现 B 接口或抽象类的方法,体现了面向接口编程的思想。