一、设计模式七大设计原则

1、七大原则简介

设计模式的七大设计原则是设计模式的基石,基本上23种设计模式的指导思想就是这七大设计原则。可以这么认为如果将设计模式比喻为盖房子的最佳实践,那么设计模式的七大原则就是指导盖房子过程中,应该怎么设计,应该怎么选材料等。
设计模式一共有七大基本原则,他们分别是:

  1. 单一职责原则
  2. 里氏替换原则
  3. 接口隔离原则
  4. 开闭原则
  5. 迪米特法则(最少知道原则)
  6. 依赖倒置原则
  7. 组合优先于继承原则

2、单一职责原则

单一职责原则,顾名思义说的就是一个实体只做一件事情,这个思想在现实生活中也很好理解,随着现代工业的发展,汽车已经十分普及了,汽车的制造流程也是相当复杂的,不是一个人一道工序就可以做好的,因此汽车的生产发展出了许多的流水线,每一个流水线上都有专门负责这个流水线上的任务,比如有些工人就只负责拧螺丝,不要小看拧螺丝这个工作,螺丝拧不好可能会对汽车的安全产生重要隐患。螺丝工人只干拧螺丝这个工作,这就是单一职责原则。
放在Java中单一职责指的是,一个对象或者一个方法只完成一件事情(引起他们变化的因素只有一个),同时方法级别的单一职责体现在,方法中的其他方法调用,必须是同一层级的,比如方法a()中调用了方法b()和c(),那么要保证在设计的时候,方法b和c要是同一级别的,所谓的同一级别就是指他们干的工作的级别是一样的,举个例子还是造汽车,a()方法是制造汽车轮子,b()方法是制造汽车玻璃,c()方法是制造汽车发动机,d()方法是组装汽车,很显然abc方法的级别是一样的,都是制造汽车的一部分零件,但是d方法的级别就要高于abc,他是负责abc生产结果的汇总,如果将他们定义在一个方法中,就违背了方法的单一职责。
单一职责原则最难处理的就是对于职责的理解,不同的业务场景以及不同的开发人员对职责的判定可能都是不一样的,因此单一职责原则没有一个统一的划定标准,还是要根据自己的实际业务进行划分。

3、开闭原则

开闭原则是设计模式7大原则中的核心原则,其他六个原则的使用都是为了满足开闭原则,开闭原则具体指的是对扩展进行开放,对修改进行关闭,所谓扩展就是指新增功能,因此遵循开闭原则的一个重要前提就是,在增加新的功能的时候,不应该修改原有的代码,而是通过额外新增代码的方式对功能进行扩展。
开闭原则是最最基本和核心的原则,但是同时也是最难掌握的原则,因为开闭原则的遵守需要一定的业务经验和抽象能力。
从工程实践的角度来说,如果一个类是我们自己设计的,那么在前期工作量不大的时候,可以修改源代码让类的功能增强以及优化,但是如果代码量比较复杂,或者这个类是别人编写的,并且无法获取到别人的源代码,抑或是能获取到源代码,但是修改起来十分复杂,那么尽量遵守开闭原则,不要轻易的修改别人的代码,很可能导致一些莫名其妙的bug。
总结一句话,不要轻易更改别人的源代码,可以在别人的代码的基础上做增强,但是不要轻易更改别人写的代码!!!

4、接口隔离原则

接口隔离原则讲的是,客户端只应该依赖它需要的接口,而不要依赖它不需要的接口,换句话说,这种依赖可以体现在方法中,也可以体现在接口实现中,体现在方法中,就是意味着我们的方法参数在声明为某个接口类型的时候,尽量保证这个接口中不包含我们这个方法不需要的方法定义,体现在接口实现中指的就是在一个类实现一个接口的时候,尽量避免这个类需要实现它不需要的接口方法。
出于上述要求,这就让我们在定义接口的时候,需要谨慎考虑定义的这个接口需要依赖哪些方法,不要什么方法都加到这个接口中,接口中的方法一定要是符合这个接口功能定义和描述的。
进一步扩展来讲,接口隔离的原则中的接口,不一定非得是Java中接口,接口可以更向上一层进行抽象,只要是对象之间的约定,都可以理解为接口,两个对象之间通过这种约定进行交互,对象之间的约定尽量保证能正常满足对象之间的交互需求即可,不要有一些和交互无关的约定。

5、依赖倒置原则

依赖倒置原则首先要明白什么是依赖,依赖在面向对象中类A的某个方法的形式参数是B的引用,B不是A的成员,那么这个时候也称A依赖B。知道了依赖的描述之后,我们来说一下什么是依赖倒置原则,依赖倒置原则的定义如下:
上层模块不应该直接依赖下层模块,应该依赖于下层模块的抽象,下层模块也不应该直接依赖上层模块,也应该直接依赖上层模块的抽象。抽象不依赖于细节,细节要依赖于抽象。大白话说就是对象之间的依赖关系应该全部建立在抽象之上,比如建立在接口上,抽象类上等等。
依赖倒置原则还有一个特别著名的名称叫做,面向接口编程,这里的接口也是指的广义上的接口,不一定就是Java中的接口,也可以是抽象类等。

6、迪米特法则(最少知道原则)

迪米特法则强调的是程序的封装性,所谓的最少知道原则,就是一个对象对其所依赖的对象知道的越少越好,如果对象A依赖了对象B,并且对象A中需要知道对象B的许多细节操作,也能完成自己的操作,那么A和B的耦合度就会变高,后期B的更改,将会导致A也发生相应的更改,不利于代码的维护和扩展。因此在迪米特法则中要求一个对象只和自己的朋友进行通信,对象可以对自己的朋友尽可能多的了解,但是对于那些不是自己朋友的对象要尽可能少的了解,所谓的了解,在编程中的体现就是调用某个对象的方法。
迪米特法则中如下几个位置出现的对象是自己的朋友:

  1. 成员变量
  2. 方法的参数
  3. 方法局部变量中,自己new出来的对象
  4. 方法的返回值

迪米特法则是一个需要权衡使用的设计模式原则,实际上这几个原则都要进行权衡使用,如果完全按照迪米特法则来编写程序,那么会导致程序中出现大量的方法,因为为了将方法中某个方法返回的对象变为朋友,所以需要定义大量的小方法,这是得不偿失的。

7、里氏替换原则

里氏替换原则是对继承的一种约束原则,里氏替换原则强调,在程序中凡是父类出现的地方,都可以直接用子类替代,不会对程序的运行结果产生改变。严格遵循里氏替换原则对我们编写重写方法时提出了如下要求:
当子类中的某个方法的方法名以及方法参数类型和父类保持一致的时候,就是子类重写了这个方法,根据动态绑定的规则,在多态调用的时候,会调用子类重写的方法,如果子类重写的方法和父类的方法产生的结果不一致,那么在程序中就没有办法直接使用子类替换父类,此外子类重写方法的返回值必须要比父类方法的返回值更加具体,并且子类抛出异常的类型也要比父类抛出的异常更加具体,如果父类没有抛出异常,那么子类也不能抛出异常,最后一点子类方法的访问控制权限不能小于父类的。
从里氏替换原则的要求上来看,基本上遵循里氏替换原则就是要求子类和父类在公有的地方要尽可能保持一致,当然子类是可以有自己不同的地方的。

8、组合优先于继承原则

组合比继承更具灵活性,继承关系在编译期间就已经确定了,一旦后期父类发生了更改,那么将会影响所有的子类,这导致后期维护比较麻烦,要求父类在设计期间就要考滤的比较周全,而组合可以在运行时利用多态动态的更改组合的对象,这就给类和类之间的关系增加了更多的灵活性。此外继承是具有侵入性的,继承会破坏父类的封装行,正是因为这种侵入性的行为,会导致封装性的破坏。

9、类和类之间的关系

9.1 三种关系介绍

在UML中将类和类之间的关系可以分为如下3种:

  1. 关联关系

关联关系描述的是一种整体和部分之间的关系,关联关系又可以细分为组合关系和聚合关系,这两个的主要区别在于,组合关系强于聚合关系,所谓的强指的是整体于部分之间的生命周期的关联性。在组合关系中整体于部分具有相同的生命周期,部分不能脱离整体存在,但是在聚合关系中,整体和部分可以具有不同的生命周期,部分可以脱离整体存在。举一个例子:大雁和雁群的关系就是聚合关系,即使少了一只大雁,其他大雁依然构成一个雁群,大雁可以单独存在。但是大雁和大雁的翅膀就是组合关系,大雁没有翅膀了就不完整了,翅膀不能脱离大雁存在。
在代码实现中,组合关系中,部分的实例化要在整体中进行,而聚合关系中,部分的实例化一般在整体之外进行。

  1. 依赖关系

如果类A的某个方法使用了类B作为形式参数,那么就称类A依赖了类B,A需要B才能完成某样功能,依赖关系更多的是体现的是一种合作关系。

  1. 继承关系

继承关系是面向对象中最常见的一种关系了,类A使用类B作为父类,那么就称类A继承自类B,其中类B称为父类,类A称为子类。

9.2 UML类图

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值