六种关系:
泛化(Generalization), 实现(Realization),关联(Association),聚合(Aggregation),组合(Composition),依赖(Dependency)。
类的关系
1、泛化(Generalization)
泛化是继承关系的一种,从更具体的角度,表示一般与特殊的关系——它指定了子类如何特征化父类的所有特征和行为。在Java中使用 extends
关键字。
比如:人是一种动物,有动物的共性(如控制自身、移动身体),但同时也有自己的特性(如会制造工具、具有强自我意识)。
//父类
public class Person {
protected String name;
protected int age;
public void move(){
}
public void say(){
}
}
//子类
public class Student extends Person {
private String studentNo;
public void tech(){
...
}
}
//子类
public class Teacher extends Person {
private String teacherNo;
public void teach(){
}
}
在UML类图中,泛化关系用实线箭头表示(用以表明子类具有父类的此项特征,在子类中就不再赘述了)。
2、实现(Realization)
实现是一种类与接口的关系,表示类是接口所有特征和行为的实现。比如在计算机中定义了一个“刷子”(接口),那么指向“刷子”的“毛笔”,与其就有以上所说的实现关系。在Java中使用 implements
关键字。
public interface Book {
public void read();
}
public class PaperBook implements Book {
public void read(){
...
}
}
public class EBook implements Book {
public void read(){
...
}
}
在UML类图中,类指向接口的虚线箭头,就表示了特定的一种实现关系。
3、关联(Association)
关联表示不同类对象之间有关联,这是一种静态关系,与运行过程无关,在最开始就可以确定;体现的是两个类、或者类与接口之间语义级别的一种强依赖关系。一般是长期性的,而且双方的关系一般是平等的。
代码层面体现为:类B以类属性的形式出现在关联类A中。
在UML类图中,关联关系用实心线箭头表示,由“主人”指向“被拥有者”(成员变量)。
关联关系一共有六种如下:
- 双向关联
- 单向关联
- 自关联
- 多重性关联
- 聚合关系
- 组合关系
双向关联
默认情况下,关联是双向的。
public class Vender {
private Product[] products;
...
}
public class Product {
private Vender vender;
...
}
单向关联
public class Car {
private Vehicle[] vehicle;
...
}
自关联
引用指向自己的类型,这和递归不同,递归是调用本身方法,这是引用本身类型的对象。
public class Node {
private Node subNode;
...
}
多重性关联
这个关联关系表示两个类型的对象在数量上之间的对应关系
换句话说就是另一个类的对象可以拥有几个该对象(从m到n的范围)
表示方式 | 多重性说明 |
---|---|
1..1 | 表示另一个类的一个对象只与该类的一个对象有关系 |
0..* | 表示另一个类的一个对象与该类的零个或者多个对象有关系 |
1..* | 表示另一个类的一个对象与该类的一个或者多个对象有关系 |
0..1 | 表示另一个类的一个对象没有或只与该类的一个对象有关系 |
m..n | 表示另一个类的一个对象与该类的零个或者多个对象有关系 |
public class Form {
private Button[] buttons; //定义为成员变量
...
}
public class Button {
...
}
4、聚合(Aggregation)
聚合是指整体与部分这一类特殊的关系,且部分可以离开整体而单独存在。如整车和轮胎是整体和部分的关系,且轮胎可以离开整车单独存在(如废旧轮胎可以用于亲子乐园中器械的制作)。
聚合关系也可以说是一种强的关联关系(即关联和聚合在语法上无法区分,必须考察具体的逻辑关系才能知晓)。
在实现的过程中通常是通过构造方法,Setter或业务方法等把成员对象注入到整体对象中。
在UML类图中,聚合关系用带空心菱形的实线箭头表示,空心菱形位于整体(而非成员变量)一侧。
public class Car{
private Engine engine;
//构造注入
public Car(Engine engine){
this.engine = engine;
}
//设值注入
public void setEngine(Engine engine){
this.engine = engine;
}
...
}
public class engine{
...
}
5、组合(Composition)
同样是整体与部分的关系,位于组合关系中的部分,不能离开整体而单独存在。比如作为部分的部门,是离不开作为整体的公司单独存在的。
同样是一种关联关系,组合关系比聚合关系的关联度,还要强。它甚至要求普通聚合关系中代表整体的对象,要负责代表部分对象的生命周期。
组合一般会在对象初始化的时候创建成员对象(new),也就是在构造方法中直接实例化成员类。并且成员变量(对象)无法脱离整体对象。
在UML类图中,组合关系用带实心菱形的实线箭头表示,实心菱形位于整体(而非成员变量)一侧。
public class Head {
private Mouth mouth;
public Head(){
mouth = new mouth();
}
...
}
public class Mouth {
...
}
6、依赖(Dependency)
和关联关系不同的是,依赖关系是在运行过程中起作用的,可以简单的理解,就是一个类A使用到了另一个类B,而这种使用关系是具有偶然性、临时性、非常弱的。
多数情况下,依赖关系体现在某个类的方法使用另一个类的对象作为参数。
在UML类图中,依赖关系用带箭头的虚线表示,箭头指向被使用者(可以是局部变量、方法的参数或者对静态方法的调用)。
public class Driver{
public void drive(Car car){
car.move;
}
}
public class Car{
public void move(){
...
}
}
Object-Relationship
六大关系的区别
组合 vs 聚合
聚合关系:弱关联,整体和部分可以独立存在。
组合关系:强关联,整体和部分不可分割,不能独立存在。
关联 vs 依赖
关联关系:A类实例化的时候需要B类的对象引用或指针作为参数。
依赖关系:A类的某个方法使用B类,可能是方法的参数是B类或在方法中获得了一个B类的实例。
某个类以成员变量的形式出现在另一个类中,二者是关联关系;某个类以局部变量的形式出现在另一个类中,二者是依赖关系。
总结
在设计模式的图纸中,常见六种软件模块间存在的关系:(1)泛化,(2)实现,(3)关联,(4)聚合,(5)组合,(6)依赖。
它们各有特点和用处(应用场景),一般来说,它们存在这样的强弱关系:泛化 ≈ 实现 > 组合 > 聚合 > 关联 > 依赖。
最后举一个人类的例子帮助记忆:
(1)泛化:动物->人
(2)实现:人->工程师
(3)组合:内脏、器官等经过组合->人
(4)聚合:工程师+工程师的鞋子(或其它附件)->(我们见到的)整个工程师
(5)关联:工程师+自己的工具(或其它拥有物)->更完整的工程师
(6)依赖:工程师+公司的工具(或其它工具)->作为完整人力资源单元的工程师
网友评论