设计模式23式——内功心法

158 阅读7分钟

设计模式是前任大牛们在开发工程中总结出来的技术结晶,而这些设计都是以六大设计原则来总结提炼的。 所以在学习这23式之前,我们需要先练习心法。

六大设计原则:

  1. 单一职责原则
  2. 里氏替换原则
  3. 依赖倒置原则
  4. 接口隔离原则
  5. 迪米特法则
  6. 开闭原则

单一职责原则:

英文描述:Single Responsibility Principle, 简称:SRP 原文解释为:There should never be more than one reason for a class to change.

在我们的开发过程中,尽量保证一个类的职责单一,但是这个划分需要多方面考虑。 虽然保证类单子职责可以降低类的复杂度,职责清晰,可读性高,可维护性高,降低变更引起的风险,但是如果生搬硬套会导致类的剧增,给维护带来非常多的麻烦,过分细分类的职责也会增加系统的复杂性,本来一个类可以是实现的行为硬拆成两个类,然后使用聚合或者组合的方式耦合在一起,人为的造成了系统的复杂性。所以原则是死,人是活的,一切看使用人如何灵活运用了。

里氏替换原则

英文描述:Liskov Substitution Principle, 简称:LSP

有两种定义:

  1. If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T,the behavior of P is unchaned when o1 is substituted for o2 then S is a subtype of T.(每一个S类型的o1对象替换T类型的o2对象,在程序P中定义T类型,而这个程序P没有任何改变,则o1是o2的子类,也就是S是T的子类)
  2. Functions that use pointers or reference to base classes must be able to use objects of derived classes without konwing it.(所有引用基类的地方必须能透明使用其子类的对象)

通俗的解释:任何子类替换父类的地方不会产生任何错误和异常。

依赖倒置原则

英文描述:Dependence inversionPrinciple,简称:DIP

定义: High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions.(高模块不应该依赖低模块,两则应该依赖其抽象,抽象不应该依赖细节,细节应该依赖抽象)

这个就是我们”面向接口编程“精髓之一,制定契约。

采用依赖倒置原则可以减少类间的耦合性,提高系统的稳定性,降低并行开发引起的风险,提高代码的可读性和可维护性。

依赖倒置原则的本质就是通过抽象(接口或抽象类)使各个类或模块的实现彼此独立,不互相影响,实现模块间的松耦合。

接口隔离原则

英文描述:Interface Segregation Principle,简称:ISP

接口分为2种:

  1. 实例接口(Object Interface),在Java中声明一个类,然后new一个实例,它是对一个类型的事务的描述,这是一种接口。Java的类也是一种接口,如:Person zhansan = new Person() ,Person类就是zhansan的接口;
  2. 类接口(Class Interface),也就是Java中interface定义的接口。

定义:

  1. Clients should not be forced to depend upon interfaces that they don't use.(客户端不应该依赖他们不需要的接口)
  2. The dependency of one class to another one should depend on the smallest possible interface.(类间的依赖关系应该建立在最小的接口上)

这个是不是感觉和单子职责很像?但两者的审视角度不同,单一职责是从业务逻辑上的划分,而接口隔离是要求接口的方法尽量少。

接口的纯洁性如何保证?

  1. 接口尽量小:但是”小“是有限度的,首先不能违背单一原则。
  2. 接口要高内聚:提高接口、类、模块的处理能力,减少对外的交互,接口中尽量少公布public方法,接口是对外的承诺,承诺越少对系统的开发越有利,变更的风险也越少,同时也有利于降低成本。
  3. 定制服务:单独为一个个体提供优良的服务,只提供访问者需要的方法。
  4. 接口设计是有限度的:接口的设计粒度越小,系统越灵活,但是同时也带了结构的复杂化,开发难度增加,可维护性降低,所以这个”度“需要根据经验和常识判断。

接口定义的衡量规则:

  1. 一个接口只服务于一个子模块或业务逻辑;
  2. 通过业务逻辑压缩接口中的public方法,接口时常去回顾,尽量精简不臃肿;
  3. 已经被污染的接口,尽量去修改,如果变更的风险较大,采用适配器模式进行转化处理;
  4. 了解环境,拒绝盲从,深入了解业务,才能设计出最好的接口。

只有实践、经验和领悟才能设计设计出好的接口。

迪米特法则

英文描述:Law of Demeter, 简称:LoD 也称为:Least Knowledge Principle, 简称:LKP 所以也叫:最少知道原则。 尽量降低类与类之间的耦合,只和朋友交流,不和陌生人说话。

迪米特法则对类的低耦合的要求:

  1. 只和朋友交流

直接朋友如何定义? 组合、聚合、依赖等

  1. 朋友间也是有距离

为了保持朋友间的距离,设计时需要反复衡量,是否减少public方法和属性,是否可以修改为private、protected等访问权限,是否可以加final关键字等。

  1. 是自己的就是自己的

如果一个方法放在本类中,即不增加类间关系,也不对本类产生负面影响,就放置在本类中。

  1. 谨慎使用Seriallzable

实现序列化的类中的属性修改,而服务器没有做响应的变更,就会报序列化失败。

迪米特法则的核心观念就是类间解耦,只有弱耦合以后,类的复用率才可以提高。 在实际应用中,如果一个类跳转两次以上才可以访问另一个类,就需要想办法重构,因为跳转次数越多,系统越复杂,维护就越困难。 原则只是供参考,采用原则师反复度量,不遵循是不对的,严格执行就是”过犹不及“。

开闭原则

英文描述:Open-closed Principle,简称:OCP

定义: Software entities like clases, modules and functions should be open for extension but closed for modifications.(一个软件实体如类、模块和函数应该对扩展开发,对修改关闭)

开闭原则对扩展开放,对修改关闭,但并不意味着不做任何修改。 变化的分类:

  1. 逻辑变化
  2. 子模块变化
  3. 可见视图变化

开闭原则的相当于一个抽象类,其他五个原则是具体的实现类。

开闭原则可以提高复用性、可维护性; 面向对象编程,对于可能变化的因素,留下接口,等待”可能“转变为”现实“。

如何使用开闭原则?

  1. 抽象约束: 1.通过接口或抽象约束扩展,进行边界限定; 2.参数类型、引用对象尽量使用接口或抽象类; 3.抽象层尽量保持稳定。
  2. 元数据控制模块行为:也就是通过配置来控制模块行为。
  3. 指定项目章程:
  4. 封装变化 1.将相同的变化封装到一个接口或抽象类中; 2.不同的变化封装到不同的接口或抽象类中。

软件设计中最大的难题就是应对需求的变化!