类关系
关系是指事物之间存在单向或相互的作用力或者影响力的状态。类与类之间的关系可分为两种:有关系与没关系,这似乎是一句非常正确的废话,难点在于确定类与类之间是否存在相互作用。证明类之间没关系是一个涉及业务、架构、模块边界的问题,往往由于业务模型的抽象角度不同,是一件非常棘手的事情。如果找到了没有关系的点,就可以如庖丁解牛一样,进行架构隔离、模块解耦等工作。有关系的情况下,包括如下5种类型:
· 【继承】 extends(is-a)
· 【实现】 implements(can-do)
· 【组合】 类是成员变量(contains-a)
· 【聚合】 类是成员变量(has-a)
· 【依赖】 import类(use-a)
继承和实现是两种比较容易理解的两种类关系。在架构设计中,要注意组合、聚合和依赖这三者的区别。 组合在汉语的含义是把若干个独立部分组成整体,各个部分都有其独立的使用价值和生命周期。而类关系中的组合是一种完全绑定的关系,所有成员共同完成一件使命,它们的生命周期是一样的。组合体现的是非常强的整体与部分的关系,同生共死,部分不能在整体之间共享。
聚合是一种可以拆分的整体与部分的关系,是非常松散的暂时组合,部分可以被拆分出来给另一个整体。
依赖是除组合和聚合外的类与类之间的关系,这个类只要import,那就是依赖关系。
在类图中,用空心的三角形表示继承,用实心的菱形表示组合,用空心的菱形表示聚合,这三者都是用实线连接的。用三角形来表示实现,用一个箭头表示依赖,与前面的区别是这两者的都是用虚线连接的。在画类图时,菱形、箭头、三角形放在哪一侧呢?在很多类图中,这个处理是非常随意的。如果方向画反了,那么类结构的认识也就反了。有一个规律,有形状的图形符号一律放在权力的强的这一侧,如表2-3所示。
类关系 | 英文名 | 描述 | 权力强侧 | 类图示例 | 示例说明 |
---|---|---|---|---|---|
继承 | Generalization | 父类与子类之间的关系:is-a | 父类方 | 小狗继承动物,完全符合里氏替换 | |
实现 | Realization | 接口与实现类之间的关系:can-do | 接口方 | 小狗实现了狗叫接口的行为 | |
组合 | Composition | 比聚合更强的关系:contains-a | 整体方 | 头只能是身体强组合的一部分,两者完全不可分,具有相同的生命周期 | |
聚合 | Aggregation | 暂时组装的关系:has-a | 组装方 | 小狗和狗绳之间是暂时聚合关系,狗绳完全可以复用在另外一条小狗上 | |
依赖 | Aggregation | 一个类用到另一个类:use-a | 被依赖方 | 人喂养小狗,小狗作为参数传人,是一种依赖关系 |
随着业务和架构发展,类与类的关系是会发生变化的,必须用发展的眼光看待类图。比如表2-3中的body和Head,如果有一天,动物的脑袋可以随时移植,那么就从组合变成聚合的关系了。狗与狗绳之间的约束,虽然很弱,但是如果防疫局在狗绳上做了疫苗记录,那么它们之间的关系就会变强,就变成组合关系了。在业务重构过程中,往往把原来的强组合的关系拆开来,供其他模块调用,这就是类图中的一种演变。