设计模式之设计原则
这软件设计过程中,有六大设计原则:
- 单一职责原则
- 里氏替换原则
- 依赖倒置原则
- 接口隔离原则
- 迪米特法则
- 开闭原则
由于软件开发过程中,根据业务不同等因素形成了各种复杂的而不可预料的需求,遵守原则,让项目开发过程与维护过程中,减少付出更多的时间与努力而达到更好的实现功能。需要对经验,不断总结,不断实践,对将设计模式使用的更熟练,对软件开发起到意想不到的作用。
以下对六大设计原则,鄙人的一些简单述说:
单一职责原则
定义:
做到有且只有一个原因引起类的变更,也就是说一个接口做一件事,这件事能概况某一事物的某一职责。
问题由来:
类T负责两个不同的职责,职责P1,职责P2,当职责P1需求发生变化时,需要修改P2功能,有可能会导致原本运行正常功能发生故障
解决方案:
将T的P1,P2两个职责使用T1,T2分别完成,T1负责P1功能,T2负责P2功能,当T1发生改变,T2不会发生改变,T2发生改变,T1也不会发生改变。
由于每个职责都进行分开,会出现大量类,当某一职责进行分解时,需要修改大量的代码,此时修改职责类中的代码违反单一职责(代码级别,方法级别),减少大量类出现。
适用情况:
- 接口
必要时可以将接口中的属性和行为进行分解,这样可以做到单一职责。 - 方法
方法中的参数过多,可以对方法的参数进行分解,可以做到单一职责。
总结:
使用接口和方法的方式,尽量做到只有一个原因引起对这个类的改变。
单一职责原则,不只是面向对象编程,还适合模块化编程等。
在实际项目中,由于功能过于复杂等原因做到该原则,还是挺难的,尽量做到单一职责原则,。
里氏替换原则
定义:
简单点说就是只要父类出现的地方,子类就可以出现,且替换成子类后,也不能出现任何错误与异常(子类出现后,父类不能因为子类的出现导致父类出问题),导致出现错误原因:子类继承父类,重写父类方法后,这时父类方法功能就失效,发生变化。
意义:
子类可以扩展父类的功能,但不能改变父类原有的功能
继承机制的优点:
- 代码共享,减少创建类的工作量
- 提高代码的重用性
- 子类可以形似父类,又异于父类,
- 提高父类的扩展性,实现父类的方法即可随意而为
缺点:
- 继承是入侵性的,(拥有父类的所有属性和方法)
- 降低了代码的灵活性,(由于父类属性的约束,导致子类的约束更多)
- 增强了耦合性,(当父类的常量,变量,方法被修改,需考虑对子类的影响)
总结: 当违反了里氏替换原则后,可以将父类和子类抽取出更加通用的基类,使用依赖,聚合,组合灯关系,降低继承的缺点。
依赖倒置原则
定义:
- 高层模块不应该依赖低层模块,两者都应该依赖其抽象
- 抽象不应该依赖细节
- 细节应该依赖抽象
在代码中可以理解成:
- 模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或者抽象类产生的
- 接口或者抽象类不依赖于实现类
- 实现类依赖于接口或者抽象类
此时可以更简洁的理解成: 面向接口编程
总结:
依赖导致原则本职就是通过抽象(抽象类或者接口)使各个类或者模块实现彼此独立,不相互影响,实现模块的松耦合。
在实际使用项目中,尽量使用如下规则:
每个类尽量都要有接口或者抽象类,或者抽象类和接口都有(依赖倒置原则定义要由抽象才能实现依赖倒置)
变量表面类型尽量是接口或者抽象类
任何类都不应该从具体类派生
尽量不要重写基类已经写好的方法(里式替换原则)
结合里式替换原则来使用(依赖原则和里式原则总结:接口负责定义public属性和方法,并声明与其他对象的依赖关系,抽象类负责公共构造部分的实现,实现类准确的实现业务逻辑,并在适当的时候对父类进行细化)
接口隔离原则
我们先来看接口的定义 :
实例接口 : 在 Java 中声明一个类,然后用 new 关键字产生一个实例,它是对一类事物的描述,可以看成是一个接口
类接口 : 使用 interface 定义的接口
隔离的的理解 :
- 客户端不应该依赖它不需要的接口
- 类之间的依赖关系应该建立在最小的接口上
概括 : 建立单一接口,不要建立臃肿庞大的接口,也就是接口尽量细化,接口中的方法尽量少
这个是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体。
接口隔离原则的约束条件 :
接口要高内聚,意思就是提高接口,类,模块的处理能力,减少对外的交互,再具体一点就是在接口中尽量减少对外的 public 方法,通过业务逻辑压缩接口中的 public 方法
定制服务,就是单独为一个个体提供优良的服务,比如我们写用户模块的时候,需要给用户提供查询信息,修改密码,注册用户等信息,当管理员执行相同操作的时候,一般人会复用这些方法,
然后在这个的基础上再增加管理员自己的方法,这种设计方法肯定是有问题的,这样设计,当你修改了普通用户调用的接口实现时,管理员的实现也会发生不可预测的改变,我们应该为管理员单独写一个接口
接口设计是有限度的,接口的设计粒度越小,系统越灵活,这是肯定的,但灵活的同时带来的问题是 结构复杂化,开发难度增加, 可维护性降低
一个接口只服务于一个子模块或业务逻辑
已经被污染了的接口,尽量去修改 ,若修改的风险较大,则采用适配器模式进行转化处理
了解环境,拒绝盲从,不要一味的去套设计模式,有的时候不用比用了更好,也不要去照搬别人的设计方法,他的方法到你这不一定效果就好,毕竟业务逻辑不一样
迪米特法则
定义 : 迪米特法则也叫最少知识原则,含义是 一个对象应该对其他对象有最少的了解,这个应该很好理解,就是降低各模块之间的耦合
开闭原则
定义 : 一个软件实体如类,模块和函数应该对扩展开放,对修改关闭,开闭原则也是其他五个原则的基石