寂然解读设计模式 - 设计模式伊始

简介: 【第一】,使用设计模式可以让软件(程序)具有更好的代码重用性,可读性,可扩展性,可靠性,让你的代码逻辑清晰,通俗来说,可以让你的代码更加优雅,可以让程序呈现出高内聚,低耦合的特性【其次】,成熟框架的源码里大量的用到了设计模式,如果掌握设计模式,对于阅读源码会有很大的帮助,而很多实际生产中的疑难杂症,其实很多时候都需要你通过源码层面去看到底是怎么写的,去反推,来解决实际问题,这就要求你很高的源码阅读能力,如果你要深入阅读源码,你懂设计模式再看的话,很多地方会非常清晰【第三】,设计模式也是对系统进行合理重构的指南针
     I walk very slowly, but I never walk backwards 

大家好~,我是寂然,本教程我们来学习设计模式,其实设计模式,好多人称之为 " Java设计模式 ",但其实设计模式并不是 Java 的专利,它不依赖语言,同样适用于 C++、C#、JavaScript 等其它面向对象的编程语言,这是首先要和大家明确的一点,Java 是典型的面向对象的编程语言,所以本教程以 Java 为基础来讲解设计模式

内容介绍

凡事预则立,不预则废,再开始学习一门新的课程之间,我们首先要来明确一下学习的内容及路线,首先,在正式的内容开始之前,我们首先要明确以下两点

  • 为什么要学习设计模式,以及设计模式的重要性

  • 设计模式的产生背景以及概念

    然后会依次给大家介绍设计模式七大设计原则,认识UML类图以及类图六大关系,设计模式的分类以及二十三种设计模式全面解析,当然,不是蜻蜓点水哈,本教程中的每一个设计模式,我会给大家采用如下路线进行全面介绍

举例应用场景 -> 设计模式介绍 -> 分析实现步骤 -> 代码案例实操 -> 框架或项目中用到该模式的源码分析

最后,希望大家通过本系列的学习,掌握多种设计模式的实现和本质,能够在工作中灵活运用解决实际问题,写出优雅并且维护性可读性高的代码,那我们开始启程吧

为什么要学设计模式

其实类似大家这样有一定工作经验的开发人员,了解以及进一步掌握设计模式是非常有必要的,因为平时大家接到开发任务,首要目标是实现功能,而且现在的节奏~,时间紧,任务重,大家没有,可能也来不及做其他的考虑,所以,大部分程序员写的代码,其实可维护性,可读性都很差,类之间的关系非常复杂,没有条理,那例如以后要增加新的需求,现有的程序如何进行变动成本最低?如何保证新的功能模块不会对原来的项目产生影响?

案例引入

举个栗子,大家看下如下两张图


part-00778-1271.jpg


茅草小屋大家应该都看到过,一个简单的架构,盖几捆茅草,他不需要什么设计,也不需要花时间合理去架构,设计他的初衷是为了遮风挡雨,大家可类比于单一的应用架构,个人开发,一个应用就能将所有的功能部署在一起,打个war包扔到tomcat里即可运行,由于模型简单,代码层面也不需要考虑太多,重点在于功能的实现


part-00186-1442.jpg


那大家来看图二的摩天大厦,一座这样的建筑,可以直接开工嘛?显示是不可以的,在项目开始之前,设计师需要画设计图纸,考虑大厦的采光,通风,安全通道,承重...,做大量的准备工作

同样,大家可以类比于现在的分布式微服务项目,随着项目的复杂度直线上升,在项目开始之前,要进行需求宣讲,架构设计评审...,这样的项目都是团队合作,除了要考虑服务之间的交互,服务内部代码的可读性,可靠性,可维护性都是我们需要重点考虑的,这时候,设计模式就显得尤为重要

设计模式可以让你知道在某些场景下如何来设计出适合场景的架构,通俗点说,可以让你的代码更加“优雅”

设计模式的重要性

当然,设计模式,大家可以通俗理解为是前辈程序员在大量开发中累积的经验,掉了大量的头发,然后归纳为了这些设计模式,当然,设计模式绝不是代表了绝对的开发真理,在问题面前应该灵活变通,当你的代码类结构合理, 易于维护 ,可扩展性强,那么设计模式的目的就已经达到了,切记不要过渡的使用设计模式,为了用而用


当然,上面的说法还是针对于大牛而言的,对于咱们这种几年经验的码农,掌握设计模式就很有必要,当大家学习并且使用到设计模式,如果你的项目做的非常大,之间关系非常复杂的时候,仍然能让你能掌控这些代码,不会出现代码失控的情况,如同上面的案例,设计模式就是设计大厦的图纸


其次,很多成熟框架的源码里大量的用到了设计模式,如果掌握设计模式,对于阅读源码会有很大的帮助,如果你要学习源码,那么学习完设计模式再看的话,会更加清晰

设计模式的背景

设计模式最早出现在建筑领域,是克里斯托弗.亚历山大(Christopher Alexander,头衔很多的大佬) 对环境中不断出现的问题, 总结出这些问题的解决方案。以后再遇到这些问题时,可以重用这些方案来解决

四人帮(GOF)

1994年,有四位作者:Erich GammaRichard HelmRalph JohnsonJohn Vlissides发表了一本题为《设计模式 - 可重用的面向对象软件元素》的图书,该书在软件开发中开创了设计模式的概念,第一次将设计模式提升到理论高度,并将之规范化,这些作者被统称为四人帮(GOF),如下就是这四个大佬~


1-1Q1121P24VM.jpg


设计模式的概念

其实,关于设计模式的概念,上面已经作出解释,当然,我们来看下设计模式的官方概念

设计模式(design pattern)是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案

这个术语是由埃里希·伽玛(Erich Gamma)等人在 1990 年代从建筑设计领域引入到计算机科学的

设计模式的原则

上面提到了,我们为什么要学习设计模式,在这里做一个简单的总结

设计模式是为了让软件(程序)具有更好的代码重用性,可读性,可扩展性,可靠性

理论听着云里雾里,那到底是什么意思呢?举个栗子,何为具有更好的可靠性呢?

  • 代码重用性:即相同功能的代码,不需要多次编写,可以重复使用
  • 可读性:即编码的规范性,便于其他程序员阅读和理解
  • 可扩展性:即当需要增加新功能时,成本低,也称为可维护性
  • 可靠性:即代码强壮,当增加新的功能时,对原有的功能没有影响

其实说到底,就是让程序呈现出高内聚,低耦合的特性

高内聚&低耦合

耦合主要描述模块之间的关系,内聚主要描述模块内部,当然模块的粒度可大可小(小到一个类 大-到一个系统)

  • 高内聚 一个功能模块内部的元素,关联越强,则内聚越高,模块的单一性更强,一个模块应当尽可能独立完成某个功能

  • 低耦合 功能模块和功能模块之间耦合性很低,A模块出现问题,避免影响B模块,比如模块A直接操作了模块B中数据, 则视为强耦合,例如下图,我们假设这样一个场景,发货系统发货,写入消息队列,订单系统这边订阅消息队列里的消息,如果订单系统出现故障,不影响发货系统正常写入消息队列,利用了消息中间件,两个系统之间的耦合性大大降低


image-20200820153605984.png


设计模式原则引出

理解了高内聚&低耦合之后,我们正式进入到设计模式七大原则,那么,何为设计模式的原则呢?

其实是程序员在编程时,应当遵守的原则,也是各种设计模式的基础 (即:设计模式为什么 这样设计的依据)

所以,我们先来认识一下设计模式常用的七大原则:

单一职责原则、接口隔离原则、依赖倒置原则、里氏替换原则、开闭原则、迪米特法则、合成复用原则

这些原则并不是孤立存在的,它们相互依赖,相互补充,下面表格对于七大原则进行了一个简单的介绍

名称 设计原则简介 重要性
单一职责原则 类的职责要单一,不能将太多的职责放在一个类中 ★★★★☆
开闭原则 软件实体对扩展是开放的,但对修改是关闭的,即在不修改一个软件实体的基础上去扩展其功能 ★★★★★
里氏代换原则 在软件系统中,一个可以接受基类对象的地方必然可以接受一个子类对象 ★★★★☆
依赖倒置原则 要针对抽象层编程,而不要针对具体类编程 ★★★★★
接口隔离原则 使用多个专门的接口来取代一个统一的接口 ★★☆☆☆
合成复用原则 在系统中应该尽量多使用组合和聚合关联关系,尽量少使用甚至不使用继承关系 ★★★★☆
迪米特法则 一个软件实体对其他实体的引用越少越好,或者说如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用,而是通过引入一个第三者发生间接交互 ★★★☆☆

设计原则和设计模式也是对系统进行合理重构的指南针,那么,何为合理重构?

合理重构,是在不改变软件现有功能的基础上,通过调整程序代码改善软件的质量、性能,使其程序的设计模式和架构更趋合理,提高软件的扩展性和维护性

下期预告

下一节,我们正式进入设计模式的学习,我会为大家用多个案例分析,来解读设计模式原则之单一职责原则,以及它的注意事项和细节,从设计模式的原则开始,一步步走进设计模式的大门,最后,希望大家在学习的过程中能够感觉到设计模式的有趣之处,高效而愉快的学习,下期见~

相关文章
|
设计模式 算法 Java
寂然解读设计模式 - 模板模式
模板模式即在一个抽象类公开定义了执行它的方法的模板,它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行,简单说,模板方法模式定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构,就可以重定义该算法的某些特定步骤
290 0
寂然解读设计模式 - 模板模式
|
设计模式 缓存 Java
寂然解读设计模式 - 代理模式
代理模式:为一个对象提供一个替身,以控制对这个对象的访问,即通过代理对象访问目标对象,这样做的好处是可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能 ,聊的通俗一点,代理模式的原理就是使用一个代理对象将目标对象包装起来,然后用该代理对象取代目标对象,代理类和被代理类有共同的父类或实现了相同的接口,这样任何对目标对象的操作都可以用代理类代替,代理类内部可以在调用目标对象的实现细节前后添加相应的业务逻辑
256 0
寂然解读设计模式 - 代理模式
|
设计模式 存储 缓存
寂然解读设计模式 - 享元模式
享元模式(Flyweight Pattern)也叫蝇量模式:运用共享技术有效地支持大量细粒度的对象 属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式,享即共享,元即对象 常用于系统底层开发,解决系统的性能问题,像数据库连接池,里面都是创建好的连接对象,在这些连接对象中有我们需要的则直接拿来用,避免重新创建,如果没有我们需要的,则重新创建
345 0
寂然解读设计模式 - 享元模式
|
设计模式 Java 数据库连接
寂然解读设计模式 - 外观模式
外观模式(Facade Pattern),也叫"门面模式",外观模式为多个复杂的子系统提供一个一致的界面 即通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问 外观模式通过定义一个一致的接口,用以屏蔽内部子系统的细节,使得调用端只需跟这个接口发生调用,而无需关心这个子系统的内部细节
257 0
寂然解读设计模式 - 外观模式
|
设计模式 存储 安全
寂然解读设计模式 - 组合模式
组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,屏蔽了对象系统的层次差异性,使用一致的行为控制不同层次,并且扩展性非常高,可以很方便地增加 树枝节点 和 叶子节点 对象,并对现有类库无侵入,满足“开闭原则”
194 0
寂然解读设计模式 - 组合模式
|
设计模式 Java 关系型数据库
寂然解读设计模式 - 装饰者模式
装饰者模式:在不改变原有对象的基础之上,动态的将功能附加到对象上,提供了比继承更有弹性的替代方案(扩展原有对象功能) ,装饰者模式也体现了开闭原则(ocp) 这里提到的动态的将新功能附加到对象和 ocp 原则,在后面的应用实例上会以代码的形式体现
233 0
寂然解读设计模式 - 装饰者模式
|
设计模式 Java API
寂然解读设计模式 - 桥接模式
桥接模式基于类的最小设计原则,通过使用封装、聚合及继承等行为让不同的类承担不同的职责,它的主要特点是把抽象与行为实现分离开来,从而可以保持各部分的独立性以及应对他们的功能扩展
309 0
寂然解读设计模式 - 桥接模式
|
设计模式 Java iOS开发
寂然解读设计模式 - 适配器模式
适配器模式:将一个类的接口转换成另一种接口,让原本接口不兼容的类可以兼容 Adapter 适配器设计模式中有 3 个重要角色: 被适配者 Adaptee,适配器 Adapter 和目标对象 Target 从用户的角度看不到被适配者,是解耦的 用户调用适配器转化出来的目标对象方法,适配器再调用被适配者的相关接口方法 用户收到反馈结果,感觉只是和目标对象交互 ,类图如下所示
285 0
寂然解读设计模式 - 适配器模式
|
设计模式 缓存 Java
寂然解读设计模式 - 建造者模式
建造者模式可以更加精细地控制产品的创建过程 ,将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,方便使用程序来控制创建过程以及顺序,增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符 合“开闭原则”
177 0
寂然解读设计模式 - 建造者模式
|
设计模式 缓存 Java
寂然解读设计模式 - 原型模式(上)
原型模式大体上有两种使用场景 一,在需要一个类的大量对象的时候,使用原型模式是最佳选择,因为原型模式是在内存中对这个对象进行拷贝,要比直接new这个对象性能要好很多,在这种情况下,需要的对象越多,原型模式体现出的优点越明显 二,如果一个对象的初始化需要很多其他对象的数据准备或其他资源的繁琐计算,那么可以使用原型模式拷贝
294 0
寂然解读设计模式 - 原型模式(上)