前言
作为设计模式系列的第一篇,我准备先分享下如何看懂UML类图,看完这篇文章,你就能看懂类图中各个类之间的关系以及线条、箭头都代表什么意思。 同时,我们会将类图所表达的含义和最终的代码实现对应起来; 有了这些知识,看后面章节的设计模式结构图就没有什么问题了。
先看一个例子
下面是我画的一张类图,使用的工具是StarUML,Mac版本下载地址
- 数码是斜体的,表示数码是一个抽象类
- 数码有两个继承类,分别是手机和电脑,他们之间的关系是实现关系,用带空心箭头的虚线表示
- iPhone与手机之间也是继承关系,他们之间的关系是泛化关系,用带空心箭头的实线表示
- 手机由屏幕和主板等组合而成,他们之间的关系是组合关系,用带实心菱形的实线表示
- 程序员上班必须要用电脑,他们之间的关系是依赖关系,用带箭头的虚线表示
- 程序员与公司之间是聚合关系,用带空心菱形的实线表示
- 程序员一般都会有自己的工牌,他们之间的关系是关联关系,用实线表示
以上例子和图中我都把类的六种关系特别标注出来了,下面我们具体讲讲这六种关系
类之间的关系
类的继承结构表现在UML中为:实现和泛化
继承关系为 is-a的关系;两个对象之间如果可以用 is-a 来表示,就是继承关系
实现(Realization)
“数码”是一个抽象概念,在现实中并不能直接用来定义对象,必须指明它的子类,比如手机和电脑。“数码”这个类在java中可以用接口或者抽象类表示,在C++中用抽象类表示。
代码实现:实现关系表现为继承抽象类。
泛化(Generalization)
手机在现实中有实现,可以用来定义具体的对象,iphone是手机的子类,手机和iphone的关系为泛化关系。
代码实现:泛化关系表现为继承非抽象类。
聚合(Aggregation)
聚合表示两个对象之间是整体和部分的弱关系,生命周期不同步,部分的生命周期可以超越整体,比如程序员和公司,公司倒闭了,但程序员还在,还可以去其他公司。
代码实现:聚合关系以成员变量的形式实现,只是成员变量的赋值时机是在类方法里,代码如下:
//第一种是在set方法里直接设置子类的实例
class Company {
private Programmer programmer;
public void setProgrammer(JavaProgrammer javaProgrammer) {
programmer = javaProgrammer;
}
}
//第二种方式是在set方法里直接写死,直接定义一个初始值
class Company {
private Programmer programmer;
public void setProgrammer() {
programmer = new JavaProgrammer();
}
}
组合(Composition)
组合表示两个对象之间是整体和部分的强关系,生命周期一致,部分的生命周期不能超越整体,或者说组合中的整体不能缺少部分。就像手机不能缺少屏幕和主板一样。
代码实现:组合关系以成员变量的形式实现,只是成员变量的赋值时机是在类构造方法里,代码如下:
//手机由屏幕组成
class Phone {
private Screen screen;
//创建手机的时候同时创建屏幕
public Phone() {
screen = new Screen();
}
}
关联(Association)
关联表示的是两个不同对象之间存在的固定的对应关系,它是一种静态关系,和运行状态无关。
代码实现:关联关系也是以成员变量的形式实现,只是成员变量的赋值时机是在声明这个变量的时候,代码如下:
//程序员都会有工牌
class Programmer {
private Card card = new Card();
}
依赖(Dependency)
依赖表示的是一个对象在运行期间会用到另一个对象的关系,与关联关系不同的是,它是一种临时性的关系,通常在运行期间产生,并且随着运行时的变化,依赖关系也可能发生变化。比如程序员在工作的时候会用到电脑,程序员是依赖电脑的。
代码实现:依赖关系主要可以通过方法参数、方法局部变量、静态方法三种方式实现,方法参数代码如下:
class Programmer {
//程序员工作的时候需要用到电脑
public void work(Computer computer) {
computer.work();
}
}