1. 单一职责
定义: 不要存在多于一个导致类变更的原因. 通俗的说, 即一个类只负责一项职责.
场景: 类 T 负责两个不同的职责: 职责 P1, 职责 P2. 当由于职责 P1 需求发生改变而需要修改类 T 时, 有可能会导致原本运行正常的职责 P2 功能发生故障.
修改: 遵循单一职责原则. 分别建立两个类 T1,T2, 使 T1 完成职责 P1 功能, T2 完成职责 P2 功能. 这样, 当修改类 T1 时, 不会使职责 P2 发生故障风险; 同理, 当修改 T2 时, 也不会使职责 P1 发生故障风险.
优点:
1), 可以降低类的复杂度, 一个类只负责一项职责, 逻辑简单;
2), 提高类的可读性, 提高系统的可维护性;
3), 变更引起的风险降低, 变更是必然的.
2. 里氏代换原则
定义: 所有引用基类的地方必须能透明地使用其子类的对象, 也就是说子类可以扩展父类的功能, 但不能改变父类原有的功能
场景: 有一功能 P1, 由类 A 完成. 现需要将功能 P1 进行扩展, 扩展后的功能为 P, 其中 P 由原有功能 P1 与新功能 P2 组成. 新功能 P 由类 A 的子类 B 来完成, 则子类 B 在完成新功能 P2 的同时, 有可能会导致原有功能 P1 发生故障.
修改: 当使用继承时, 遵循里氏替换原则. 类 B 继承类 A 时, 除添加新的方法完成新增功能 P2 外, 尽量不要重写父类 A 的方法, 也尽量不要重载父类 A 的方法.
3. 依赖倒置原则
定义: 高层模块不应该依赖低层模块, 二者都应该依赖其抽象; 抽象不应该依赖细节; 细节应该依赖抽象.
此处理解起来是最困难的, 一般会在项目框架的搭建的时候用到, 例如, 业务逻辑层相对于数据层是高层模块, 因为业务逻辑层需要调用数据层去连接数据库, 但是要做到可扩展高复用, 尽量不要让业务逻辑层依赖数据层, 可以在数据层抽象出一个接口, 让业务逻辑层依赖于这个抽象接口.
场景: 类 A(高层模块) 直接依赖类 B(低层模块), 假如要将类 A 改为依赖类 C(低层模块), 则必须通过修改类 A 的代码来达成. 这种场景下, 类 A 一般是高层模块, 负责复杂的业务逻辑; 类 B 和类 C 是低层模块, 负责基本的原子操作; 假如修改类 A, 会给程序带来不必要的风险.
AutoSystem 类直接依赖于 HondaCar 与 FordCar 两个类, 这样就产生了一个高耦合, AutoSystem 类想操控 HondaCar 或者 FordCar 必须直接创建相应对象.
修改: 将类 A 修改为依赖接口 I, 类 B 和类 C 各自实现接口 I, 类 A 通过接口 I 间接与类 B 或者类 C 发生联系, 则会大大降低修改类 A 的几率, 如下图:
经过此番修改, Honda 与 Ford 实现 ICar 接口, 提供了 Run,Stop 以及 Turn 功能方法, AutoSystem 依赖 ICar 接口, 这样迫使 AutoSystem 依赖抽象接口, 这就使得 AutoSystem 类能够应对更多的需求变化.
优点:
1), 低层模块尽量都要有抽象类或接口, 或者两者都有.
2), 变量的声明类型尽量是抽象类或接口.
3), 使用继承时遵循里氏替换原则.
4. 接口隔离原则
定义: 客户端不应该依赖它不需要的接口; 一个类对另一个类的依赖应该建立在最小的接口上.
场景: 类 A 通过接口 I 依赖类 B, 类 C 通过接口 I 依赖类 D, 如果接口 I 对于类 A 和类 B 来说不是最小接口, 则类 B 和类 D 必须去实现他们不需要的方法, 如下图:
修改: 将臃肿的接口 I 拆分为独立的几个接口, 类 A 和类 C 分别与他们需要的接口建立依赖关系. 也就是采用接口隔离原则.
注意:
1), 接口尽量小, 但是要有限度. 对接口进行细化可以提高程序设计灵活性 是不挣的事实, 但是如果过小, 则会造成接口数量过多, 使设计复杂化. 所以一定要适度.
2), 为依赖接口的类定制服务, 只暴露给调用的类它需要的方法, 它不需要的方法则隐藏起来. 只有专注地为一个模块提供定制服务, 才能建立最小的依赖关系.
3), 提高内聚, 减少对外交互. 使接口用最少的方法去完成最多的事情.
5. 迪米特法则 (最少知道原则)
定义: 一个对象应该对其他对象保持最少的了解.
场景: 类与类之间的关系越密切, 耦合度越大, 当一个类发生改变时, 对另一个类的影响也越大.
简单的理解就是高内聚, 一个类尽量减少对其他对象的依赖, 并且这个类的方法和属性能用私有的就尽量私有化.
注意:
1), 只与直接的朋友通信, 不要和陌生人说话.
2), 过分的使用该原则, 将导致系统复杂度变大. 所以在采用迪米特法则时要反复权衡, 既做到结构清晰, 又要高内聚低耦合.
6. 开闭原则
定义: 一个软件实体如类, 模块和函数应该对扩展开放, 对修改关闭.
场景: 在软件的生命周期内, 因为变化, 升级和维护等原因需要对软件原有代码进行修改时, 可能会给旧代码中引入错误, 也可能会使我们不得不对整个功能进行重构, 并且需要原有代码经过重新测试.
建议: 当软件需求变化时, 尽量通过扩展软件实体的行为来实现变化, 而不是通过修改已有的代码来实现变化.
来源: http://www.bubuko.com/infodetail-2552736.html