设计模式之六大设计原则

六大原则

[toc]

1.单一原则

  • 应该有且仅有一个原因引起类的变更
  • 单一职责原则要求一个接口或类只有一个原因引起变化,也就是一个接口或类只有一个职责,它就负责一件事情
image.png

建议

接口一定要做到单一职责,类的设计尽量做到只有一个原因引起变化。

2. 里氏替换原则

只要父类能出现的地方子类就可以出现
4层含义

  • 子类必须完全实现父类的方法
  • 子类可以有自己的个性
  • 覆盖或实现父类的方法时输入参数可以被放大
  • 覆写或实现父类的方法时输出结果可以被缩小


    image.png

建议

在项目中,采用里氏替换原则时,尽量避免子类的“个性”,一旦子类有“个性”,这个子类和父类之间的关系就很难调和了,把子类当做父类使用,子类的“个性”被抹杀——委屈了点;把子类单独作为一个业务来使用,则会让代码间的耦合关系变得扑朔迷离——缺乏类替换的标

3. 依赖倒置原则

  • 高层模块不应该依赖低层模块,两者都应该依赖其抽象;
  • 抽象不应该依赖细节;
  • 细节应该依赖抽象

高层模块和低层模块容易理解,每一个逻辑的实现都是由原子逻辑组成的,不可分割的原子逻辑就是低层模块,原子逻辑的再组装就是高层模块。那什么是抽象?什么又是细节呢?在Java语言中,抽象就是指接口或抽象类,两者都是不能直接被实例化的;细节就是实现类,实现接口或继承抽象类而产生的类就是细节,其特点就是可以直接被实例化,也就是可以加上一个关键字new产生一个对象。依赖倒置原则在Java语言中的表现就是:模块间的依赖通过抽象发生,实现类之间不发生直接的依赖关系,其依赖关系是通过接口或抽象类产生的;接口或抽象类不依赖于实现类;实现类依赖接口或抽象类。更加精简的定义就是“面向接口编程”——OOD(Object-Oriented Design,面向对象设计)的精髓之一

image.png

建议

  1. 每个类尽量都有接口或抽象类,或者抽象类和接口两者都具备
  2. 变量的表面类型尽量是接口或者是抽象类
  3. 任何类都不应该从具体类派生
  4. 尽量不要覆写基类的方法
  5. 结合里氏替换原则使用
    • 接口负责定义public属性和方法,并且声明与其他对象的依赖关系,抽象类负责公共构造部分的实现,实现类准确的实现业务逻辑,同时在适当的时候对父类进行细化

4. 接口隔离原则

建立单一接口,不要建立臃肿庞大的接口。再通俗一点讲:接口尽量细化,同时接口中的方法尽量少

跟单一原则区别:

接口隔离原则与单一职责的审视角度是不相同的,单一职责要求的是类和接口职责单一,注重的是职责,这是业务逻辑上的划分,而接口隔离原则要求接口的方法尽量少

image.png

建议:

一个接口只服务于一个子模块或业务逻辑;

5. 迪米特法则

最少知识原则(Least KnowledgePrinciple,LKP),虽然名字不同,但描述的是同一个规则:一个对象应该对其他对象有最少的了解。通俗地讲,一个类应该对自己需要耦合或调用的类知道得最少,你(被耦合或调用的类)的内部是如何复杂都和我没关系,那是你的事情,我就知道你提供的这么多public方法,我就调用这么多,其他的我一概不关心


image.png

建议:

迪米特法则的核心观念就是类间解耦,弱耦合,只有弱耦合了以后,类的复用率才可以提高。其要求的结果就是产生了大量的中转或跳转类,导致系统的复杂性提高,同时也为维护带来了难度

6.开闭原则

开闭原则是Java世界里最基础的设计原则,它指导我们如何建立一个稳定的、灵活的系统

软件实体应该对扩展开放,对修改关闭,其含义是说一个软件实体应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化

image.png

三种变化

  • 逻辑变化
    只变化一个逻辑,而不涉及其他模块,比如原有的一个算法是ab+c,现在需要修改为ab*c,可以通过修改原有类中的方法的方式来完成,前提条件是所有依赖或关联类都按照相同的逻辑处理。
  • 子模块变化
    一个模块变化,会对其他的模块产生影响,特别是一个低层次的模块变化必然引起高层模块的变化,因此在通过扩展完成变化时,高层次的模块修改是必然的,刚刚的书籍打折处理就是类似的处理模块,该部分的变化甚至会引起界面的变化。
  • 可见视图变化
    可见视图是提供给客户使用的界面,如JSP程序、Swing界面等,该部分的变化一般会引起连锁反应

使用开闭原则原因

  1. 首先,开闭原则非常著名,只要是做面向对象编程的,甭管是什么语言,Java也好,C++也好,或者是Smalltalk,在开发时都会提及开闭原则。
  2. 其次,开闭原则是最基础的一个原则,前五章节介绍的原则都是开闭原则的具体形态,也就是说前五个原则就是指导设计的工具和方法,而开闭原则才是其精神领袖。换一个角度来理解,依照Java语言的称谓,开闭原则是抽象类,其他五大原则是具体的实现类,开闭原则在面向对象设计领域中的地位就类似于牛顿第一定律在力学、勾股定律在几何学、质能方程在狭义相对论中的地位,其地位无人能及。
  3. 最后,开闭原则是非常重要的,可通过以下几个方面来理解其重要性。
    • 开闭原则对测试的影响
    • 开闭原则可以提高复用性
    • 开闭原则可以提高可维护性
    • 面向对象开发的要求

如何使用:

  • 抽象约束
    [图片上传失败...(image-563c0f-1604134136019)]
  • 元数据(metadata)控制模块行为

尽量使用元数据来控制程序的行为,减少重复开发。什么是元数据?用来描述环境和数据的数据,通俗地说就是配置参数,参数可以从文件中获得,也可以从数据库中获得。举个非常简单的例子,login方法中提供了这样的逻辑:先检查IP地址是否在允许访问的列表中,然后再决定是否需要到数据库中验证密码(如果采用SSH架构,则可以通过Struts的拦截器来实现),该行为就是一个典型的元数据控制模块行为的例子,其中达到极致的就是控制反转(Inversion of Control),使用最多的就是Spring容器,在SpringContext配置文件中

  • 制定项目章程

在一个团队中,建立项目章程是非常重要的,因为章程中指定了所有人员都必须遵守的约定,对项目来说,约定优于配置

  • 封装变化

对变化的封装包含两层含义:第一,将相同的变化封装到一个接口或抽象类中;第二,将不同的变化封装到不同的接口或抽象类中,不应该有两个不同的变化出现在同一个接口或抽象类中。封装变化,也就是受保护的变化(protectedvariations),找出预计有变化或不稳定的点,我们为这些变化点创建稳定的接口,准确地讲是封装可能发生的变化,一旦预测到或“第六感”发觉有变化,就可以进行封装,23个设计模式都是从各个不同的角度对变化进行封装的,我们会在各个模式中逐步讲解

注意事项

  • 开闭原则也只是一个原则
  • 项目规章非常重要
  • 预知变化

你可能感兴趣的:(设计模式之六大设计原则)