# 面向对象设计原则
SOLID
原则 + 迪米特法则
# 单一责任原则(Single Responsibility Principle)
一个类只允许有一个职责,即只有一个导致该类变更的原因。
类的职责要单一
优点:
- 降低类的复杂度
- 提高类的可读性,进而提高系统的可维护性
- 降低变更引起的风险(降低对其他功能的影响)
# 开放封闭原则(Open/Closed Principle)
一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
总纲,对扩展开放,对修改关闭
优点:
- 稳定性。开闭原则要求扩展功能不修改原来的代码,这可以让软件系统在变化中保持稳定。
- 扩展性。开闭原则要求对扩展开放,通过扩展提供新的或改变原有的功能,让软件系统具有灵活的可扩展性。 遵循开闭原则的系统设计,可以让软件系统可复用,并且易于维护。
为了满足开闭原则的对修改关闭以及扩展开放的原则,应该对软件系统中的不变的部分加以抽象成接口,这些不变的接口可以应对未来的扩展。
接口可以被复用,但接口的实现却不一定能被复用。
接口是稳定的,关闭的,但接口的实现是可变的,开放的。
可以通过对接口的不同实现以及类的继承行为等为系统增加新的或改变系统原来的功能,实现软件系统的柔性扩展。
开闭原则的相对性:软件系统的构建是一个需要不断重构的过程,在这个过程中,模块的功能抽象,模块与模块间的关系,都不会从一开始就非常清晰明了,所以构建100%满足开闭原则的软件系统是相当困难的,这就是开闭原则的相对性。 但在设计过程中,通过对模块功能的抽象(接口定义),模块之间的关系的抽象(通过接口调用),抽象与实现的分离(面向接口的程序设计)等,可以尽量接近满足开闭原则。
# 里氏替换原则(Liskov Substitution Principle)
所有引用基类的地方必须能透明地使用其子类的对象,也就是说子类对象可以替换其父类对象,而程序执行效果不变。
子类可以透明替换父类
优点:
- 约束继承泛滥,是开闭原则的一种体现。
- 加强程序的健壮性,同时变更时也可以做到非常好地提高程序的维护性、扩展性,降低需求变更时引入的风险。
# 接口隔离原则(Interface Segregation Principle)
多个特定的客户端接口要好于一个通用性的总接口。
接口的职责要单一
- 一个类对一个类的依赖应该建立在最小的接口上
- 建立单一接口,不要建立庞大臃肿的接口
- 尽量细化接口,接口中的方法尽量少
接口分隔原则的优点和适度原则:
- 接口分隔原则从对接口的使用上为我们对接口抽象的颗粒度建立了判断基准:在为系统设计接口的时候,使用多个专门的接口代替单一的胖接口。
- 符合高内聚低耦合的设计思想,从而使得类具有很好的可读性、可扩展性和可维护性。
- 注意适度原则,接口分隔要适度,避免产生大量的细小接口。
单一职责原则和接口分隔原则的区别
单一职责强调的是接口、类、方法的职责是单一的,强调职责,方法可以多,针对程序中实现的细节;
接口分隔原则主要是约束接口,针对抽象、整体框架。
# 依赖倒置原则(Dependency Inversion Principle)
- 依赖抽象,而不是依赖实现。
- 抽象不应该依赖细节;细节应该依赖抽象。
- 高层模块不能依赖低层模块,二者都应该依赖抽象。
面向接口编程
优点:可以减少类间的耦合性、提高系统稳定性,提高代码可读性和可维护性,可降低修改程序所造成的风险。
# 迪米特法则(Law of Demeter)
又叫最少知道原则(Least Knowledge Principle),一个对象应该对尽可能少的对象有接触,也就是只接触那些真正需要接触的对象。
降低耦合
真正需要接触的对象:
- 当前对象本身(
this
) - 以参量形式传入到当前对象方法中的对象
- 当前对象的实例变量直接引用的对象
- 当前对象的实例变量如果是一个聚集,那么聚集中的元素也都是朋友
- 当前对象所创建的对象
迪米特原则不希望类直接建立直接的接触。如果真的有需要建立联系,也希望能通过它的友元类来转达。因此,应用迪米特原则有可能造成的一个后果就是: 系统中存在大量的中介类,这些类之所以存在完全是为了传递类之间的相互调用关系,这在一定程度上增加了系统的复杂度。
例如,购房者要购买楼盘A、B、C中的楼,他不必直接到楼盘去买楼,而是可以通过一个售楼处去了解情况,这样就减少了购房者与楼盘之间的耦合,如图所示。
参考文档
← 中介者模式 消除代码中的if(一) 💯 →