经典23种设计模式总结

3 篇文章 0 订阅

系列文章目录

第一章 经典23种设计模式总结
第二章 常见的设计原则
第三章 重构



前言

每个码农工作1-2年后,就不是仅仅完成导师或者领导安排的user story,还要考虑如何编写高质量的代码,确保的user story背后隐藏的非功能需求,即常说的代码的可维护性,可读性,可拓展性,灵活性,简洁性,可复用性,可测试性。我们可以通过设计思想,设计原则,设计模式,编码规范,重构这五个方面来提高代码的质量。
经典23种设计模式,是前辈们在不断coding过程中总结出来的处理特定类型的问题的处理方式,下面对经典23中设计模式进行总结。众所周知,经典23种设计模式,可以分成三种:创建型、结构型、行为型。

一、创建型

创建型主要包括单例模式,工厂模式,建造者模式,原型模式(不常用)。主要是解决对象的创建问题,封装复杂的创建过程,解耦对象的创建代码和使用代码。

1.单例模式

一般都是进程内一个类只允许创建一个实例,那这个类就是单例类。一般用在数据在系统只保存一份,如:配置信息。目前Spring中,写的controller、service、component一般都是单例模式。单例模式的实现方式,有很多种,主要包括,详细的代码可以参考:Java版单例模式实现

  • 饿汉式:使用instance静态实例,保证线程安全,但是不支持延迟加载实例。
  • 懒汉式:支持延迟加载实例,但是使用synchronzed锁,性能低。
  • 双重检测:支持延迟、又支持高并发,但是可以通过反序列化、反射等手段破坏单例模式。
  • 静态内部类:利用Java静态内部类实现单例,既支持高并发,实现简单,但是可以通过反序列化,反射等手段破坏单例模式。
  • 枚举:基于枚举实现的单例模式,最简单,保证单例的唯一性。

2.工厂模式

工厂模式用来创建不同但是相关类型的对象,由给定的参数来决定创建那种类型的对象。Spring IOC和Google Guice都用工厂模式来管理实例的创建。工厂模式又可以分为:

  • 简单工厂:当每个对象的创建逻辑都比较简单的时候,推荐使用简单工厂模式,将多个对象的创建逻辑放在一个工厂类中。
  • 工厂方法:当每个对象的创建逻辑都比较复杂的时候,为了避免设计一个过于庞大的工厂类,推荐使用工厂方法模式,将创建逻辑拆分得更细,将每个对象的创建逻辑独立到各自的工厂类中。
  • 抽象工厂:

3.建造模式

建造模式,也叫着Builder模式,主要是用来解决构造函数入参过多的情况。

  • 类的必填属性放到构造函数中,强制创建对象的时候就设置。如果必填的属性有很多,把这些必填属性都放到构造函数中设置,那构造函数就又会出现参数列表很长的问题。
  • 如果类的属性之间有一定的依赖关系或者约束条件。
  • 对象在创建好之后,就不能再修改内部的属性值。

4.原型模式

如果对象的创建成本比较大,而同一个类的不同对象之间差别不大(大部分字段都相同),在这种情况下,我们可以利用对已有对象(原型)进行复制(或者叫拷贝)的方式,来创建新对象。一般原型模式,可以分为:

  • 深拷贝:深拷贝得到的是一份完完全全独立的对象,简单的方式可以通过BeanUtile进行copy,或者通过序列化再反序列化的方式。
  • 浅拷贝:浅拷贝只会复制对象中基本数据类型数据和引用对象的内存地址,不会递归地复制引用对象,以及引用对象的引用对象。

二、结构型

结构型主要包括:代理模式、桥接模式、装饰器模式、适配器模式、门面模式(不常用)、组合模式(不常用)、享元模式(不常用)。总结了一些类或者对象组合在一起的经典结构,这些经典的结构可以解决特定应用场景的问题。

1.代理模式

代理模式在不改变原始类接口的条件下,为原始类定义一个代理类,主要目的是控制访问,而非加强功能。主要是用在业务系统的非功能需求开发,如:监控、统计、鉴权、限流、事务、幂等、日志等。主要分为静态代理,动态代理。目前主要使用动态代理。

2.桥接模式

桥接模式,可以有两种理解方式:

  • 将抽象和实现解耦,让它们能独立开发
  • 组合优于继承

3.装饰器模式

装饰者模式在不改变原始类接口的情况下,对原始类功能进行增强,并且支持多个装饰器的嵌套使用。

4.适配器模式

适配器模式是一种事后的补救策略。适配器提供跟原始类不同的接口,而代理模式、装饰器模式提供的都是跟原始类相同的接口。主要用在如下场景:

  • 封装有缺陷的接口设计
  • 统一多个类的接口设计
  • 替换依赖的外部系统
  • 兼容老版本接口
  • 适配不同格式的数据

5.门面模式

门面模式为子系统提供一组统一的接口,定义一组高层接口让子系统更易用。主要用在如下场景:

  • 解决易用性问题
  • 解决性能问题
  • 解决分布式事务问题

6.组合模式

组合模式跟我们之前讲的面向对象设计中的“组合关系(通过组合来组装两个类)”,完全是两码事。这里讲的“组合模式”,主要是用来处理树形结构数据。正因为其应用场景的特殊性,数据必须能表示成树形结构,这也导致了这种模式在实际的项目开发中并不那么常用。

7.享元模式

在内存中只保留一份实例,供多处代码引用,这样可以减少内存中对象的数量,以起到节省内存的目的。Java SDK中Integer 和 String在设计中都有使用享元模式。

三、行为型

型设计模式主要解决的就是“类或对象之间的交互”问题。行为型模式比较多,有 11 种,它们分别是:观察者模式、模板模式、策略模式、职责链模式、迭代器模式、状态模式、访问者模式(不常用)、备忘录模式(不常用)、命令模式(不常用)、解释器模式(不常用)、中介模式(不常用)。

1.观察者模式

在对象之间定义一个一对多的依赖,当一个对象状态改变的时候,所有依赖的对象都会自动收到通知。观察者模式,使用的场景很多,如:邮件订阅、RSS、Vue、WPF。具体的实现方式可以参考guava。

2.模板模式

模板方法模式在一个方法中定义一个算法骨架,并将某些步骤推迟到子类中实现。模板方法模式可以让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。模板模式主要使用在处理流程大概一致,但是又有一些细节区别,如:Spring Bean的加载流程。个人认为模板模式、策略模式是最能体现开闭原则设计模式,具有如下特点:

  • 复用:所有的子类可以复用父类中提供的模板方法的代码
  • 拓展:框架通过模板模式提供功能扩展点,让框架用户可以在不修改框架源码的情况下,基于扩展点定制化框架的功能

3.策略模式

定义一族算法类,将每个算法分别封装起来,让它们可以互相替换。策略模式可以使算法的变化独立于使用它们的客户端

4.职责链模式

将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。使用场景:

  • http filter
  • UGC
  • Spring Interceptor

5.迭代器模式

迭代器模式将集合对象的遍历操作从集合类中拆分出来,放到迭代器类中,让两者的职责更加单一。

6.状态模式

状态机有 3 个组成部分:状态(State)、事件(Event)、动作(Action)。其中,事件也称为转移条件(Transition Condition)。事件触发状态的转移及动作的执行。实现方式:

  • 分支逻辑法:利用 if-else 或者 switch-case 分支逻辑,参照状态转移图,将每一个状态转移原模原样地直译成代码
  • 查表法:对于状态很多、状态转移比较复杂的状态机来说,查表法比较合适。通过二维数组来表示状态转移图,能极大地提高代码的可读性和可维护性
  • 状态模式:对于状态并不多、状态转移也比较简单,但事件触发执行的动作包含的业务逻辑可能比较复杂的状态机来说,推荐这种实现方式

7.访问者模式

访问者模式允许一个或者多个操作应用到一组对象上,设计意图是解耦操作和对象本身,保持类职责单一、满足开闭原则以及应对代码的复杂性。编程语言一般分为两种学派:

  • Single Dispatch:指的是执行哪个对象的方法,根据对象的运行时类型来决定;执行对象的哪个方法,根据方法参数的编译时类型来决定。
  • DoubleDispatch: 指的是执行哪个对象的方法,根据对象的运行时类型来决定;执行对象的哪个方法,根据方法参数的运行时类型来决定。
    Java就是Single Dispatch。

8.备忘录模式

在不违背封装原则的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便之后恢复对象为先前的状态。主要使用在防丢失,撤销、恢复的场景。

9.命令模式

命令模式将请求(命令)封装为一个对象,这样可以使用不同的请求参数化其他对象(将不同请求依赖注入到其他对象),并且能够支持请求(命令)的排队执行、记录日志、撤销等(附加控制)功能

10.解释器模式

解释器模式为某个语言定义它的语法(或者叫文法)表示,并定义一个解释器用来处理这个语法。

11.中介模式

中介模式定义了一个单独的(中介)对象,来封装一组对象之间的交互。将这组对象之间的交互委派给与中介对象交互,来避免对象之间的直接交互。

四、总结

经典23种设计模式,是前人的经验总结,可以解决现实工作中特定场景的一些问题。但是也要根据实际的场景来选择,最好的实践方式是在不确定的情况下,优先选择最简单的实现方式,若后面有修改的需求,再进行重构。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值