前言
在实践中经常看到工厂模式、观察者模式等字眼,渐觉设计模式的重要性,于是开刷设计模式。
本文讲述了UML类图以及设计模式的六大原则
参考资料:
课程视频:黑马程序员Java设计模式
一、UML类图
1. 类和接口的表示方式
如图所示,在 UML 类图中,第一栏为类的名称,第二栏为类的属性(field),第三栏为类的方法(method)
属性/方法之前的 - + # 表示访问权限:
- 表示 private
+ 表示 public
# 表示 protected
属性的完整表示方式是: 可见性 名称 :类型 [= 缺省值]
方法的完整表示方式是: 可见性 名称(参数列表)[:返回类型]
接口图 和 类图 的主要区别是顶端有 <<interface>>
2. 关联和双向关联
关联关系表示存在对象的引用,如 A 类中某一个成员变量的类型为 B 类,那么 A 类依赖于 B 类
关联关系使用 实心箭头 表示
双向关联使用 横线 表示
3. 组合和聚合
组合 和 聚合 都是关联的特例,强调整体和部分的关系,在转换为关系模型时跟关联没有区别,但是在
UML 中的描述存在语义上的区别。
组合
组合 中的整体和部分具有强依赖,整体的对象负责部分的对象的生命周期,如鸟和翅膀
组合关系用 实心菱形+横线/实线箭头 表示
聚合
而聚合的整体和部分可以独立存在,如汽车和轮胎,部门和员工
聚合关系用 空心菱形+横线/实线箭头 表示
3. 依赖、继承、实现
依赖
依赖是一种使用关系,它是对象之间耦合度最弱的一种关联方式,是临时性的关联。
表示一个类中的方法通过 局部变量、方法的参数或者对静态方法 的调用来访问另一个类(被依赖类)中的某些方法来完成一些职责。
依赖关系用 虚线箭头 表示
继承
继承关系是对象之间耦合度最大的一种关系,表示一般与特殊的关系,是父类与子类之间的关系
继承关系用 空心三角实线箭头 表示
实现
实现关系是接口与实现类之间的关系。在这种关系中,类实现了接口,类中的操作实现了接口中所声明的所有的抽象操作。
实现关系用 空心三角虚线箭头 表示
二、六大设计原则
1. 开闭原则
开闭原则 即 对扩展开放,对修改关闭
在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。
简言之,是为了使程序的扩展性好,易于维护和升级。
实现方式是使用 接口 和 派生类
2. 里氏代换原则
里氏代换原则 即 任何基类可以出现的地方,子类一定可以出现
通俗理解: 子类可以扩展父类的功能,但不能改变父类原有的功能
换句话说,子类继承父类时,除添加新的方法完成新增功能外,尽量不要重写父类的方法
【例子】
如果让 正方形类 继承 长方形类(包含 setLength(), setWidth()方法)
那么正方形类会重写长方形类的这两个方法,以实现自身的逻辑,从而违反里氏代换原则
修正方案:
新建 Quadrilateral 接口,让长方形和正方形分别去实现该接口,而使用长方形的类依赖该接口
3. 依赖倒转原则
依赖倒转原则 即 高层模块不应该依赖低层模块,两者都应该依赖其抽象;
抽象不应该依赖细节,细节应该依赖抽象。简单的说就是要求对抽象进行编程
不要对实现进行编程,这样就降低了客户与实现模块间的耦合。
【例子】
电脑有多种配件比如cpu,显卡,显示器
电脑不应该依赖于特定品牌的cpu,显卡,显示器,也就是不能依赖于实现
而是应该依赖于cpu,显卡,显示器它们的抽象
4. 迪米特法则
迪米特法则 又叫最小知识法则
其含义是: 如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。
其目的是降低类之间的耦合度,提高模块的相对独立性。
迪米特法则的
【例子】
明星通过经纪人组织与粉丝的见面会
甲方公司通过乙方公司把需求拍给牛马
5. 接口隔离原则
接口隔离原则 即 客户端不应该被迫依赖于它不使用的方法; 一个类对另一个类的依赖应该建立在最小的接口上。
实现上采用将 包含多个方法的接口 分解为 多个只包含少量方法的接口
【例子】
一个品牌的安全门实现了 防火、防水、防盗
另一个品牌的安全门实现了 防火、防水
若定义接口 包含 防火、防水、防盗 三个功能,那么第二个类就被迫依赖于它不使用的防盗方法
故定义三个接口分别为 防火、防水、防盗
6. 合成复用原则
合成复用原则 即 尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。
继承会将父类的细节暴露给子类,破坏了类的封装性,使子类与父类耦合度高,限制了复用的灵活性。
【例子】
现有父类为汽车,子类继承汽车,分别为汽油汽车和新能源汽车,孙子类继承汽油汽车/新能源汽车再拓展不同颜色的汽车
可见,再给汽车增加一种类型的动力源时,会出现很多的孙子类,扩展性很差。
修改方案:
父类为汽车,包含颜色属性(聚合颜色这一接口,而颜色这一接口可被各种颜色所实现),子类继承汽车使用不同的动力源