开足码力,码动人生,微信搜索【 程序员大帝 】,关注这个一言不合就开车的的代码界老司机
本文 GitHub上已经收录 https://github.com/BeKingCoding/JavaKing , 一线大厂面试核心知识点、我的联系方式和技术交流群,欢迎Star和完善

前言

设计模式是前辈们用毕生心血专业填坑换来的经验,把这些经验加工精简,就成了设计模式,也就是套路。有了套路,就能让我们加快软件的开发速度和扩展性(听起来怎么好像是 PUA 的感觉)。

设计模式包含了大量的编程思想,真正掌握并不容易,在学习每种具体的模式之前,咱们今天先来看看需要遵循的七大原则。相信大家耐心看了之后肯定有收获,码字不易,别忘了「在看」,「转发」哦。

  • 单一职责原则

  • 开闭原则

  • 里氏替换原则

  • 依赖倒转原则

  • 合成复用原则

  • 接口隔离原则

  • 迪米特法则

正文

01 单一职责原则

单一职责原则( Single Responsibility Principle )为我们提供了一个编写程序的准则,目的是把导致其变更因素的缩减到最少(比如你约妹子吃饭,起码提前看看天气预报再约时间)。

如果一个类承担的职责过多,就等于把这些职责耦合在一起。

一个职责的变化可能会影响或损坏其他职责的功能。而且职责越多,这个类变化的几率就会越大,类的稳定性就会越低。

所谓是闻道有先后,术业有专攻。做人也要避免样样都玩,样样都不精,在设计类的时候,要使其功能职责单一纯碎,把本职工作做到最好。

我们在软件开发中,需要面临很多任务,比如任务 T1,任务 T2,如果让一个类C负责这两个不同的任务。需求变更的时候,要对任务 T1 的代码修改来满足新的业务需求。

可会发现 T1 代码的修改竟然会导致原本能够正常运行的 T2 发生错误,而修复 T2 又不得不回过头再去对T1的修改,这便是因为类 C 的职责不够单一,把任务 T1 与任务 T2 耦合在一起导致的。

02 开闭原则

开闭原则( Open-Closed Principle )明确的告诉我们:软件实现应该对扩展开放,对修改关闭。

简单来说,功能应该通过扩展来实现变化, 而不是通过修改已有的代码来实现变化。

为什么要遵循开闭原则?

(1)开闭原则堪称是最基础的设计原则,是精神领袖。在 Java 语言中,抽象类就是开闭原则的一种非常好的体现。

(2)开闭原则可以提高维护性。一款应用的诞生到运行,开发软件可以说是一次性的工作,真正让人头疼的是在后期的维护与扩展。随着我们的应用越来越流行,用户越来越多,产品经理肯定要不停地提各种需求。

现在各大公司人员更新迭代速度明显加快,“每年输出一千名阿里工作10年以上的人才”。

连网友都翻出这句话编写段子:

“都是裁员,马老师说的就是那么有大局观。华为:放弃平庸员工。腾讯:结构性优化。百度:鼓励狼性,淘汰小资。蔚来:局部优化,提高运营效率。科大讯飞:提前吃饭的员工需要被优化。京东:淘汰掉因身体原因不能拼搏的员工。”

扯远了,如果你入职接手了别人的项目,如果让你从头开始读一遍原来的代码,然后再根据新的需求修改老代码,这是非常痛苦的事情,简直可以说是精神上的折磨和摧残。

但是如果我们仅仅是进行扩展,那么事情就会变得容易很多。

(3)开闭原则可以提高代码的复用性。在面向对象的设计中,所有的逻辑都是从原子逻辑组合而来,不是在一个类中独立实现一个业务逻辑。只有这样的代码才可以复用,粒度越小,被复用的可能性越大。

如何使用开闭原则?

万物皆发展变化,有变化就要有策略去应对,怎么快速应对呢?这就需要在设计之初考虑到所有可能变化的因素,然后留下接口,等待“可能”转变为“现实”。

使用 Java 编程时,抽象类和接口是这种思想最好的体现。通过对一组事物的通用描述,没有具体的实现,代表它可以有非常多的可能性,可以跟随需求的变化而变化。

同时我们为这些变化创建稳定的接口时,具体可以有两种操作方式:

将相同的变化封装到一个接口或抽象类中。

将不同的变化封装到不同的接口或抽象类中,不应该有两个不同的变化出现在同一个接口或抽象类中。

03 里氏替换原则

Java 中为我们提供了继承的实现,那么在整个系统中,里氏替换原则( Liskov Substitution Principle )指的是,如果一个地方可以接受某个基类,那么必然也可以接受这个基类的子类。

比如一个方法接收的参数是类型P,那么如果将其替换成 T 的子类 C,程序的行为不应该发生变化。

使用里氏原则也要遵循几个行为准则:

(1)假设类 B 继承类 A 时,B 可以添加新的方法完成新增的功能,但不要重写父类 A 的方法,也不要重载父类A的方法。

这里再说重载( overload )重写( override ) 的区别:

重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!

重载是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。

每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。

最常用的地方就是构造器的重载。

(2)如果随着业务的扩展,需要对基类 A 和子类 B 进行重构,应该让它们去继承一个更加通用的基类。

(3)里氏替换原则可以正着用,但是不能反着用,在子类出现的地方,父类未必可以胜任。

04 依赖倒转原则

大家刚听到这些名词都会觉得云里雾里,依赖倒转原则( Dependency Inversion Principle )简单来说就是:

(1)高层模块不应该依赖于低层模块,二者都应该依赖于抽象。

(2)抽象不应该依赖细节;细节应该依赖抽象。

还不明白?

其实大家在平时编程时候已经不自觉地使用了依赖倒转原则,核心思想就是面向接口编程。

接口就是一种抽象,只要不修改接口声明,大家可以放心大胆调用,至于接口的内部实现则无需关心,可以随便重构。

这里,接口就是抽象,而接口的实现就是细节。

只要接口是稳定的,那么任何一个的更改都不用担心其他的受到影响,这就使得无论高层模块还是低层模块都可以很容易地被复用。

依赖倒转原则是一种通识,具体用哪种语言来编写程序并不重要,设计的出发点就是为了应对变化的问题。

再举一个生活中的例子,电脑里的内存卡槽,其实就是一种接口。只要符合这个接口的要求,无论是用金士顿的内存,还是其它牌子的内存,无论是4G的,还是8G的,都可以很方便、轻松的插到电脑上使用。

05 接口隔离原则

通过上面几个规则我们已经知道,面向接口编程促进了代码的解耦,并使架构体系更加鲁棒。

但一个东西再好吃也要适度,所以就提出了接口隔离原则( Interface Segregation Principle )。主要目的是为了对接口的使用进行约束规范,它告诉我们要想把接口用好,关键在于隔离。

隔离,指断绝接触、断绝往来。

那么我们使用接口时,要隔离什么东西呢:

(1)客户端不应该依赖它不需要的接口,这个很容易理解,在实践中也很容易实现。

(2)类间的依赖关系应该建立在最小的接口上,它要求“最小的接口”,也就是该接口中没有多余的方法,所以这里的隔离是指和多余的方法隔离。

综上所述,接口隔离原则告诉我们,不要把一大堆方法塞进一个接口里,导致这个接口变得臃肿无比。应该要根据实际需要,让接口中只有用得上的方法,也就是说要细化我们的接口。

接口隔离原则的要点,就是要细化我们的接口。那么这样做具体有什么好处呢:

  • 避免接口污染
  • 提高灵活性
  • 提供定制服务
  • 实现高内聚

06 合成复用原则

合成复用原则(Composite Reuse Principle)字面意思说的很清楚,写代码时应该尽量使用对象组合,而不是使用继承来达到复用的目的。

使用继承来实现复用非常简单,但没有足够的灵活性,只能在有限的环境中使用。

假设一个子类继承了父类的所有方法,但是如果父类当中有方法被改变了,子类当中就找不到相应的方法,造成子类出错。

为了避免这种情况的出现,第一是父类专门为扩展而设计,几乎不会改变,并提供完整的文档,第二是父类和子类在同一个包下面,都由同一个程序员负责,保证好父类的改变能够及时通知到子类当中。

显而易见,无论哪种方式都不够灵活。

组合复用的耦合度相对较低,可以在运行时动态选择性地调用成员对象进行操作,使系统更加灵活,一个类的变化对其他类造成的影响相对较少。

因此一般首选使用组合/聚合来实现复用;其次才考虑继承,在使用继承时,需要严格遵循里氏代换原则,有效使用继承会有助于对问题的理解,降低复杂度,而滥用继承反而会增加系统构建和维护的难度以及系统的复杂度,因此需要慎重使用继承复用。

07 迪米特原则

迪米特原则(Law of Demeter)也被称为最少知识原则,一个对象应该对其他实体依赖越少越好。迪米特法则的核心在于类间的解耦,只有弱耦合之后类的复用率才会提高。

我们用人际交往来说,大家平时肯定和自己朋友交流得最多,但朋友之间也是有距离的。

对别人不能暴露太多,否则二次修改的时候,会让影响的范围增大,这也要求类间public方法不能肆无忌惮的暴露。

信息的隐藏可以使各个子系统之间脱耦,从而允许它们独立地被开发、优化、使用和修改。

依赖的模块越少,它能够独立在其他地方使用的能力越强。构建一个大规模的系统时,信息的隐藏显得尤其重要。

如果模块A和模块B都强依赖于模块C,那么A和B的开发进度都可能就会需要跟着C来走,一个功能C无法完成,A和B也无法继续开发。

同时如果和陌生人交往时,要抱有一定的戒心,有互相相信的朋友作为中间人最好。

如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用,而是通过引入一个第三者发生间接交互。


Offer收割机》系列持续更新,也会定期分享互联网常用技术栈相关的文章,GitHub 上已经收录 https://github.com/BeKingCoding/JavaKing ,讲解一线大厂面试要求的核心知识点、并有对标阿里P7级别的成长体系脑图,欢迎加入技术交流群,我们一起有点东西。

我是一言不合就开车的代码界老司机无忌。创作不易,各位的支持和认可,就是我创作的最大动力,我们下篇文章见!

大白话设计模式七大原则相关推荐

  1. Java面试之设计模式七大原则

    最近项目不太忙,不怎么加班,正利用晚上时间好好学习学习设计模式,之前可能多多少少都用到过,但是有些还是很模糊,这下正好系统的学一下. 好了,话不多说,进入正题. 1.什么是设计模式? 软件工程中,设计 ...

  2. 第 2 章 设计模式七大原则

    第 2 章 设计模式七大原则 1.设计模式的目的 编写软件过程中,程序员面临着来自 耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性 等多方面的挑战, 设计模式是为了让程序(软件),具有如下更好的 ...

  3. 设计模式——七大原则(附代码示例)

    一. 设计模式概念         对接口编程而不是对实现编程:优先使用对象组合而不是继承 二. 设计模式总览 1. 创建型模式(Creational Patterns):(5) 单例(Singlet ...

  4. 设计模式——七大原则

    设计模式--七大原则 汇总篇 1.单一职责 2.接口隔离 3.依赖倒转 4.里氏代换原则 5.开闭原则 6.迪米特法则 7.合成复用 汇总篇 1.单一职责 对类来说的,即一个类应该只负责一项职责.如类 ...

  5. 图解设计模式-设计模式七大原则

    Java设计模式 设计模式七大原则 设计模式的目的 编写软件过程中,程序员面临来自 耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性等多方面的挑战,设计模式是为了让 **程序(软件)**具有更好的 ...

  6. Day305.设计模式七大原则 -Java设计模式

    七大设计原则 一.设计模式的目的 编写软件过程中,程序员面临着来自 耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性 等多方面的挑战,设计模式是为了让程序(软件),具有更好的↓↓↓ 1. 代码重用 ...

  7. Java设计模式七大原则-单一职责原则

    目录 概述:设计模式的目的 设计模式七大原则 单一职责原则 单一职责原则注意事项和细节 概述:设计模式的目的 编写软件过程中,程序员面临着来自 耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性 等 ...

  8. 设计模式七大原则介绍

    文章目录 1. 设计模式有哪些种类 2. 设计模式的目的 3. 设计模式七大原则 3.1. 单一职责原则 1. 基本介绍 2. 模拟场景 2. 接口隔离原则 1. 基本介绍 2. 模拟场景 3. 依赖 ...

  9. 设计模式七大原则知识概括

    设计模式七大原则知识概括 设计模式的目的 设计模式七大原则 单一职责原则 接口隔离原则 依赖倒转(倒置)原则 里氏替换原则 开闭原则 迪米特法则 合成复用原则 设计原则核心思想 设计模式的目的 目的: ...

最新文章

  1. wordpress关闭博客评论的两种方法
  2. 【周末阅读】人工智能时代基础数据服务大有可为
  3. 【Kotlin】Kotlin 领域特定语言 DSL 原理 一 ( DSL 简介 | 函数 / 属性扩展 )
  4. 一般将来时语法课教案_【语法视频课】第43~45节(虚拟语气)
  5. 【ARM】Tiny4412裸机编程之GPIO简介
  6. android 运行jar包,android将so打到jar包中并运行-Go语言中文社区
  7. [PAT乙级]1017 A除以B
  8. 怎样自动提取邮件的内容_这些最新的外贸搜索开发工具(图灵搜、谷歌搜索提取工具、易查查),你会使用吗?...
  9. 建德有没有计算机培训,建德计算机培训,建德计算机培训班,建德计算机培训完好找工作吗 - IT教育频道...
  10. 索引-linux-技术大钢
  11. k1658停运到什么时候_2020年春节快递几号停运 2020年春节快递停运时间电商春节放假通知...
  12. 2017百度之星程序设计大赛 - 资格赛
  13. dms虚拟服务器,取得dms服务器ip
  14. MPC控制笔记(一)
  15. ofdm导频信道估计matlab,ofdm系统中基于导频的信道估计算法的性能分析(样例3)...
  16. mysql命令行常用命令_mysql命令行常用命令
  17. 服务器无法远程的原因
  18. 微生太 | 宏基因组分箱Binning(一)基础介绍与报告展示
  19. 高德地图开发-- 自定义图标
  20. 基于spring boot的奖助学金评审系统毕业设计源码031035

热门文章

  1. 乔坟往事-麦收与秋收
  2. 如何同时操作三台服务器
  3. 战地2(BF2)手动窗口化方法
  4. 心田花开一年级语文四季知识点汇总教案
  5. 转来的:Diablo中的七大套装背景
  6. 骁龙870和麒麟990 哪个好
  7. vue兄弟组件之间的通信的使用
  8. 扬州掼蛋游戏网JS特效详解
  9. Equitech-Bio纯化人免疫球蛋白IgG冻干粉说明书
  10. 程序员怎么保护我们的眼镜,延长使用期限?