在六种关系中,从弱到强排列分别是:依赖、关联、聚合、组合、继承、实现。
关联是类与类之间的一种结构关系。
其中聚合和组合都是关联的特殊种类,表示了整体和部分的关系。
如果类A方法中仅仅使用了类B中的对象,那么类A依赖于类B。
如果类A控制类B的生命周期,那么类A和类B是组合关系。
关系名称 | 具体关系 | 区别体现 |
---|---|---|
依赖 | 使用关系(语义关系) | 对象a只调用对象b的服务 |
关联 | 结构关系 | 对象a能够获得对象b的实例并调用服务 |
若类A单向关联指向类B,则在类A中存在一个属性B b,即类B以属性的方式存在于类A。
若类A依赖类B,则不会有这个属性,类B的实例可能存在于某个方法调用的参数中,或某个方法的局部变量中。
关系名称 | 具体关系 | 区别体现 |
---|---|---|
聚合 | 弱的结构关系(整体和部分) | 整体不存在,部分存在 |
组合 | 强的结构关系(整体和部分) | 整体不存在,部分也不存在 |
关系名称 | 具体关系 | 区别体现 |
---|---|---|
继承 | 一般与特殊 | 将同语义层元素连接,通常在同一模型内 |
实现 | 语义关系 | 将不同语义层元素连接,通常在不同模型内 |
概念:依赖是六大关系中最弱的关系,是一种弱的关联。它是两个事物之间的语义关系,是一种使用关系,表现为一个对象仅仅是调用了另一个对象的服务,其中一个事物(独立事物)发生变化会影响另一个事物(依赖事物)的语义。
具体体现:
通常使用类库就是其中的一种提现,比如在程序中调用了sqrt()开方函数,还有在A类中用到B类,即B类以方法参数或者方法中的局部变量等形式出现在A中。
代码体现如下:
public class Clothes {
private String clothesName="大风衣";
public String getClothesName() {
return this.clothesName;
}
}
public class Food {
private String food="糖醋里脊";
public String getAceType() {
return this.food;
}
}
public class Person {
private String name;
public void showInfo(Food food,Clothes clothes) {
System.out.println(name+"穿"+clothes+"吃"+food);
}
}
在这个例子中,人类依赖于衣服类和食物类,如果没有衣服类跟食物类,人就不能吃跟穿,并且衣服和食物一改变也会影响人类的变化。
概念:关联是一种结构关系,它描述了一组对象之间连接的链,有单向关联、双向关联和自身关联(只涉及一个类),链上可以添加多重度,角色名称,说明关联的对象数量以及行为等。在关联关系中又有特殊的类型——聚合和组合,用于描述部分和整体之间的结构关系。
具体体现:
自关联:自己包含自己
单向关联:类A知道类B,而不需要类B知道类A。(类B作为类A的属性)
代码体现:
public class Teacher {
private String tchName="小明";
public String getTchName() {
return this.tchName;
}
}
public class Student {
private String stuName;
Teacher xiaoMing=new Teacher();
public void showInfo() {
System.out.println(xiaoMing.getTchName()+"教了这位"+stuName+"同学");
}
}
在UML图中,关联关系用实线的箭头表示,如下所示:
在这个例子中,单向关联,学生类单向new了老师这个对象,并调用了这个对象的方法。
双向关联:类A需要知道类B,而类B也需要知道类A。(类AB互为对方的属性)
代码体现:
public class Student {
private String stuName="狗蛋";
Teacher xiaoMing=new Teacher();
public void showInfo() {
System.out.println(xiaoMing.getTchName()+"教了这位"+stuName+"同学");
}
public String getStuName() {
return this.stuName;
}
}
public class Teacher {
private String tchName="小明";
Student gd=new Student();
public String getTchName() {
return this.tchName;
}
public void showInfo() {
System.out.println("学生"+gd.getStuName()+"是我的学生");
}
}
在这个例子中,双向关联,学生类new了老师这个对象,老师类也new了学生这个对象,互相调用了各自的方法。
概念:聚合可以理解为一组引用的集合(引用的合成),整体不存在,但是部分可以单独存在。体现的是整体和部分拥有的关系,整体和部分之间是可以分离的,各自具有各自的生命周期,部分可以属于多个整体对象,也可以为多个整体对象共享,聚合暗示子类型独立于父类型而存在。
具体体现:
比如学生和老师组成一个班级,班级解散后,老师和学生还可以单独存在。是has-a的关系,班级 has a student。
类似的还有员工与部门,你跟你的家庭,主板上的各部件和主板的关系等。
代码体现:
public class Student {
private String stuName="狗蛋";
public String getStuName() {
return this.stuName;
}
}
public class Teacher {
private String tchName="小明";
public String getTchName() {
return this.tchName;
}
}
在UML类图中用空心菱形加箭头表示,菱形指向整体,如下图所示:
在这个例子中,班级是整体,老师和学生都是部分,当班级不存在的时候,老师和学生还可以单独存在,比如说,狗蛋升学了,他所在的这个三年二班已经不在了,他的老师小明也去教别的班去了。
概念:组合可以理解为一组值的集合(值的合成),整体不存在,部分也就不存在。是一种很强的拥有关系。类A的部分由类B的对象组成,并且类A控制类B的生命周期。组合暗示没有父类型,子类型无法存在。整体和部分之间共生死。
具体体现:
页面和书的关系,四肢和人的关系等,他们具有contains-a的关系。
代码体现:
public class Page {
private int pageNums=100;//页数
private String pageType="护眼纸张";//纸的类型
public int getPageNums() {
return pageNums;
}
public String getPageType() {
return pageType;
}
}
public class Book {
private String bookName="金刚经";
Page num1=new Page();
public void showBookInfo() {
System.out.println(bookName+"由"+num1.getPageNums()+"页的"
+num1.getPageType()+"型的纸类型构成");
}
}
在UML类图中用实心菱形加箭头表示,菱形指向整体,如下图所示:
在这个例子中,书跟页面是组合的关系,页面不能独立于书而存在。
概念:继承又叫做泛化,是一个类和它的一个或多个细化类之间的关系,即一般与特殊的关系。特殊元素(子元素)的对象可替代一般元素(父元素)的对象[里氏代换],用这种方法,子元素共享了父元素的结构和行为。
具体体现:
动物类和猫类之间的关系,交工工具类和飞机类之间的关系,猫类is a 动物类,他们具有 is a 的关系。
代码体现:
public class Animal {
public void eat() {
System.out.println("动物会吃东西");
}
public void speak() {
System.out.println("动物会吼叫");
}
}
//猫类重写了父类的方法
public class Cat extends Animal{
public void eat() {
System.out.println("猫吃老鼠");
}
public void speak() {
System.out.println("猫会喵喵叫");
}
}
在这个例子中,猫类继承动物类,可以对父类的方法进行重载,使用extends关键字继承父类,可以继承父类除私有方法和属性以外的一切方法跟属性。
概念:实现是类元之间的语义关系,其中一个类元指定了由另一个类元保证执行的契约。
具体体现:
java通过接口来实现多继承,一个接口或者抽象类,定义好一组操作,由具体的实现类去完成接口的具体操作。
代码体现:
public interface PaoMian {
public void jiashui();//往泡面加热水
public void waitTime();//等待泡面泡熟
public void eatMian();//开吃
}
public class EatPaoMian implements PaoMian{
@Override
public void jiashui() {
// TODO 自动生成的方法存根
System.out.println("往泡面加入热水");
}
@Override
public void waitTime() {
// TODO 自动生成的方法存根
System.out.println("等待三分钟...");
}
@Override
public void eatMian() {
// TODO 自动生成的方法存根
System.out.println("泡面熟了,开吃");
}
}
在这个例子中,抽象接口泡面定义了三个操作:加水、等待、开吃,而吃泡面这个类实现了这个接口,具体化了泡面这个流程操作。