《设计模式之禅》六大设计原则2
接口隔离原则
接口隔离原则的定义
接口分为两种:
● 实例接口(Object Interface),在Java中声明一个类,然后用new关键字产生一个实
例,它是对一个类型的事物的描述,这是一种接口。Java中的类也是一种接口。
● 类接口(Class Interface),Java中经常使用的interface关键字定义的接口。
那什么是隔离呢?它有两种定义,如下所示:
● Clients should not be forced to depend upon interfaces that they don't use.(客户端不应该依
赖它不需要的接口。)
● The dependency of one class to another one should depend on the smallest possible interface.
(类间的依赖关系应该建立在最小的接口上。)
可以把这两个定义概括为一句话:建立单一接口,不要建立臃肿庞大的接口。再通
俗一点讲:接口尽量细化。
接口隔离原则是对接口进行规范约束,其包含以下4层含义:
● 接口要尽量小,但是“小”是有限度的,首先就是不能违反单一职责原则
根据接口隔离原则拆分接口时,首先必须满足单一职责原则。
● 接口要高内聚
什么是高内聚?高内聚就是提高接口、类、模块的处理能力,减少对外的交互。具体到接口隔离原则就是,要求在接口中尽量少公布public方法,接口是对外的承诺,承诺越少对系统的开发越有利,变更的风险也就越少,同时也有利于降低成本。
● 定制服务
什么是定制服务?定制服务就是单独为一个个体提供优良
的服务。我们在做系统设计时也需要考虑对系统之间或模块之间的接口采用定制服务。采用
定制服务就必然有一个要求:只提供访问者需要的方法。
● 接口设计是有限度的
接口的设计粒度越小,系统越灵活
最佳实践
接口隔离原则是对接口的定义,同时也是对类的定义,接口和类尽量使用原子接口或原
子类来组装。
原子该怎么划分?在实践中可以根据以下几个规则来衡量:
● 一个接口只服务于一个子模块或业务逻辑;
● 通过业务逻辑压缩接口中的public方法,接口时常去回顾
● 已经被污染了的接口,尽量去修改,若变更的风险较大,则采用适配器模式进行转化
处理;
● 了解环境,拒绝盲从。
迪米特法则
迪米特法则的定义
迪米特法则(Law of Demeter,LoD)也称为最少知识原则(Least Knowledge
Principle,LKP),即一个对象应该对其他对象有最少的了解。
迪米特法则对类的低耦合提出了明确的要求,其包含以下4层含义。
1. 只和朋友交流
迪米特法则还有一个英文解释是:Only talk to your immediate friends(只与直接的朋友通
信。)什么叫做直接的朋友呢?每个对象都必然会与其他对象有耦合关系,两个对象之间的
耦合就成为朋友关系,这种关系的类型有很多,例如组合、聚合、依赖等。
朋友类的定义是这样的:出现在成员变量、方法的输入输出参数中的类称为成员朋友类,而出现在方法体内部的类不属于朋友类
注意 一个类只和朋友交流,不与陌生类交流
2. 朋友间也是有距离的
注意 迪米特法则要求类“羞涩”一点,尽量不要对外公布太多的public方法和非静态的
public变量,尽量内敛,多使用private、package-private、protected等访问权限。
3. 是自己的就是自己的
如果一个方法放在本类中,既不增加类间关系,也对本类不产生负面影响,那就放置在本类中。
4. 谨慎使用Serializable
最佳实践
迪米特法则的核心观念就是类间解耦,弱耦合,只有弱耦合了以后,类的复用率才可以
提高。其要求的结果就是产生了大量的中转或跳转类,导致系统的复杂性提高,同时也为维
护带来了难度。
开闭原则
开闭原则的定义:
Software entities like classes,modules and functions should be open for extension but closed formodifications.(一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。)
开闭原则的定义已经非常明确地告诉我们:软件实体应该对扩展开放,对修改关闭,其
含义是说一个软件实体应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化。
软件实体包括以下几个部分:
● 项目或软件产品中按照一定的逻辑规则划分的模块。
● 抽象和类。
● 方法。
注意 开闭原则对扩展开放,对修改关闭,并不意味着不做任何修改,低层模块的变
更,必然要有高层模块进行耦合,否则就是一个孤立无意义的代码片段。
可以把变化归纳为以下三种类型:
● 逻辑变化
● 子模块变化
● 可见视图变化
开闭原则是非常重要的
1. 开闭原则对测试的影响
2. 开闭原则可以提高复用性
在面向对象的设计中,所有的逻辑都是从原子逻辑组合而来的,而不是在一个类中独立
实现一个业务逻辑。只有这样代码才可以复用,粒度越小,被复用的可能性就越大。
3. 开闭原则可以提高可维护性
4. 面向对象开发的要求
如何使用开闭原则
1. 抽象约束
抽象是对一组事物的通用描述,没有具体的实现,也就表示它可以有非常多的可能性,
可以跟随需求的变化而变化。因此,通过接口或抽象类可以约束一组可能变化的行为,并且
能够实现对扩展开放,其包含三层含义:第一,通过接口或抽象类约束扩展,对扩展进行边
界限定,不允许出现在接口或抽象类中不存在的public方法;第二,参数类型、引用对象尽
量使用接口或者抽象类,而不是实现类;第三,抽象层尽量保持稳定,一旦确定即不允许修
改。
2. 元数据(metadata)控制模块行为
什么是元数据?用来描述环境和数据的数据,通俗地说就是配置参数
3. 制定项目章程
4. 封装变化
对变化的封装包含两层含义:第一,将相同的变化封装到一个接口或抽象类中;第二,
将不同的变化封装到不同的接口或抽象类中,不应该有两个不同的变化出现在同一个接口或
抽象类中。封装变化,也就是受保护的变化(protected variations),找出预计有变化或不稳
定的点。