23种设计模式(软考中级 软件设计师)

23种设计模式(软考中级 软件设计师)

news/2024/5/14 5:52:05/ 标签: 设计模式

设计模式


23个设计模式,23个意图

1. 设计模式概要

设计模式的核心在于提供了相关问题的解决方案,使得人们可以更加简单方便的复用成功的设计和体系结构

设计模式的类别

创建型结构型行为型
工厂方法模式适配器模式(类)解释器模式
模版方法模式
对象抽象工厂模式
生成器模式
原型模式
单例模式
适配器模式(对象)
桥接模式
组合模式
装饰模式
外观模式
享元模式
代理模式
责任链模式
命令模式
迭代器模式
终结者模式
备忘录模式
观察者模式
状态模式
策略模式
访问者模式

2. 创建型设计模式

2.1 工厂模式(简单工厂模式)

属于创建型但不属于23中设计模式之一

意图:

定义一个工厂类,他可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类

违背了开闭原则

2.2 工厂方法模式(Factory Method)

意图:

定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法模式使一个类的实例延迟到其子类

主要角色:

  • 抽象工厂:提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品。(体现了多态)
  • 具体工厂:主要是实现抽象工厂中的抽象方法,完成具体产品的创建
  • 抽象产品:定义了产品的规范,描述了产品的主要特性和功能
  • 具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,同具体工厂一一对应

比如:

咖啡工厂接口(抽象工厂):有创建咖啡对象的方法。其下有两个具体工厂(美式咖啡工厂和拿铁咖啡工厂),他们去实现父类的接口,重写父类的方法。由具体工厂生成具体产品,再由具体产品(美式咖啡和拿铁咖啡)实现抽象产品(咖啡)

由此要增加产品类时相应地增加工厂类,不需要修改工厂类的代码了

注:interface接口 对应 implements实现

优点:

  • 用户只需要知道具体工厂的名称就可以得到所要的产品,无需知道产品的具体创建过程
  • 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无需对原工厂进行任何修改,满足开闭原则(对扩展开放,对修改关闭)

缺点:

  • 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,增加了系统的复杂度

题目描述:

  • 当一个类不知道它所必须创建的对象的类的时候
  • 当一个类希望由它的子类来指定它所创建的对象的时候
  • 当类将创建对象的职责委托各多个帮助子类中的某一个,并且你希望将哪一个帮助子类时代理这一信息局部化的时候
2.3 抽象工厂模式

意图

提供一个创建一系列相关或相互依赖对象的接口,且访问类无需指定它们具体的类

抽象工厂模式是工厂方法模式的升级版,工厂方法模式只能生产一个等级的产品,而抽象工厂模式可以生成多个等级的产品

主要角色:

  • 抽象工厂:提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品
  • 具体工厂:主要是实现抽象工厂中的抽象方法,完成具体产品的创建
  • 抽象产品:定义了产品的规范,描述了产品的主要特性和功能,抽象工厂有多个抽象产品
  • 具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,同具体工厂一一对应

比如:

咖啡店不仅要生成咖啡还要生成甜品,比如提拉米苏、抹茶慕斯等,按照工厂方法模式,需要定义提拉米苏类、提拉米苏方法、抹茶慕斯类、抹茶慕斯方法,容易发生类爆炸情况。抽象工厂中,拿铁咖啡、美式咖啡是一个产品等级(咖啡),提拉米苏、抹茶慕斯是一个产品等级(甜点),拿铁咖啡、提拉米苏是同意产品族(意大利风味),美式咖啡、抹茶慕斯是同一产品族(美式风味)

即抽象工厂接口下有两个具体工厂(意大利风味和美式风味),两个具体工厂生成其下相应地具体产品,再由具体产品去实现抽象产品(咖啡和甜点)

优点:

  • 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象

缺点:

  • 当产品族中需要增加一个新的产品时,所有的工厂都需要修改

题目描述:

  • 提供一系列相关或相互依赖的对象的接口,而无需指定这些对象所属的具体类
  • 当一个系统应该独立于它的产品创建、组合和表示时
  • 当要强调一系列相关的产品对象的设计以便进行联合使用时
  • 一个系统要由多个产品系列中的一个来配置时
  • 为图形用户界面(GUI)组件定义不同平台的并行类层次结构

使用场景:

  • 当需要创建的对象是已一系列相互关联或相互依赖的产品族时,如:电器工厂中的电视机、洗衣机、空调等
  • 系统中有多个产品族,但每次只使用其中的某一族产品。如:有人只喜欢穿某一个品牌的衣服和鞋
  • 系统中提供了产品的类库,全且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构
    如:输入发换皮肤,一整套一起换,生成不同操作系统 程序
2.4 生成器模式(建造者模式)

意图

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示

主要角色:

  • 抽象建造者类:这个接口规定要实现对象的那些部分的创建,并不涉及具体部件对象的创建
  • 具体建造者类:实现Builder接口,完成复杂产品的各个部件的具体创建方法,在构造过程完成后,提供产品的实例
  • 产品类:要创建的负责对象
  • 指挥者类:调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建

比如:

分离了部件的构造(由Builder来负责)和装配(Director负责),从而可以构造出负责的对象,这个模式使用于某个对象的构建过程复杂的情况
由于实现了构建和装配的解耦,不同的构建器,相同的装配,也可以做出不同的对象;相同的构建器,不同的装配顺序也可以做出不同的对象。也就是实现了构建算法、装配算法的解耦,实现了更好的复用
建造者模式可以将部件和其组装过程分开,一步一步创建一个复杂的对象,用户只需要指定复杂对象的类型就可以得到该对象,而无需知道其内部的具体构造细节

优点:

  • 封装性很好
  • 客户端不必知道产品内部组成的细节
  • 可以更加精细地控制产品的创建过程
  • 容易进行扩展

缺点:

  • 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制

题目描述:

  • 当创建复杂对象的算法应该独立于该对象的组成部分及其装配方式时
  • 当构造过程必须允许被构造的对象有不同的表示时
  • 将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示
  • 适用于抽象复杂对象的构建步骤和基于构建过程的具体实现构建复杂对象的不同表示
  • 关键字:复杂对象,不同的表示

使用场景:

建造者模式创建的是复杂对象,其产品的各个部分经常面临着剧烈的变化,但将它们组合在一起的算法却相对稳定,所以它通常在以下场合使用

  • 创建的对象较复杂,由多个部件构成,个部件面临着复杂的变化,但构件间的建造顺序是稳定的
  • 产品的构建过程和最终表示是独立的
2.5 原型模式

意图

用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象(用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象

主要角色:

  • 抽象原型类:规定了具体原型对象必须实现的clone()方法
  • 具体原型类:实现抽象原型类的clone()方法,它是可被复制的对象
  • 访问类:使用具体原型类中的clone()方法来复制新的对象

比如:

同一学校的”三好学生“奖状除了获奖人姓名不同,其他相同,可以使用原型模式复制多个”三好学生“奖状出来,然后修改奖状上的名字即可

即由抽象原型类下的具体原型类重写父类接口中的clone,由访问类复制对象

题目描述:

  • 应该类的实例只能有几个不同状态组合中的一种
  • 当一个系统应该独立于它的产品创建、构成和表示时
  • 当要实例化的类是在运行时刻指定是,例如:通过动态装载
  • 为了避免创建一个与产品类层次平行的工厂类层次时
  • 当一个类的实例只能有几个不同状态组合中的一种时,建立相应数目的原型并克隆他们,可能比每次用合适的状态手工实例化该类更方便些

使用场景:

  • 对象的创建非常复杂,可以使用原型模式快捷的创建对象
  • 性能和安全要求比较高
2.6 单例模式(选择题)

意图

保证一个类仅有一个实例,并提供一个访问它的全局访问点

题目描述:

  • 它能够保证一个类只产生唯一的一个实例

  • 一个类仅有一个实例

  • 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时

  • 当这个唯一实例应该是通过之类化可扩展的,并且客户无需更改代码就能使用一个扩展的实例时

2.7 创建型设计模式总结
创建型设计模式定义关键字
工厂方法模式(Factory Method)定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法模式使一个类的实例延迟到其子类子类决定实例化
抽象工厂模式(Abstract Factory)提供一个创建一系列相关或相互依赖对象的接口,且访问类无需指定它们具体的类抽象接口
构建者模式(生成器模式)(Builder)将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示类和构造分离
原型模式(Prototype)用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象原型实例,拷贝
单例模式(Singleton)保证一个类仅有一个实例,并提供一个访问它的全局访问点唯一实例

3. 结构型设计模式

3.1 适配器模式

分为类和对象型,类适配器模式使用继承,类之间的耦合度比对象型高,且要求程序员了解现有组件库中的相关组件的内部结构,所以应用相对较少;对象适配器模式使用聚合、组合

意图

将一个类的接口转换成客户希望的另外一个接口,适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作

主要角色:

  • 目标接口:当前系统业务所期待的接口,它可以是抽象类或接口
  • 适配者类:它是被访问和适配的现存组件库中的组件接口
  • 适配器类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者

比如:

类型:定义一个适配器来实现当前系统的业务接口,同时又继承现有组件库中已经存在的组件
对象型:将现有组件库中已经实现的组件引入适配器类中,该类同时实现当前系统的业务接口
现有一台电脑只能读SD卡。而要读取TF卡中的内容就需要使用适配器模式,创建一个读卡器,将TF卡中的内容读取出来

注:类适配器模式违背了合成复用原则,类适配器是客户类有一个接口规范的情况下可用,反之不可用

题目描述:

  • 将一个对象加以包装以给客户提供其希望的另外一个接口
  • 想使用一个已经存在的类,而其接口不符合要求
  • 使所有接口不兼容类可以一起工作
  • 将一个类的接口转换成客户希望的另一个接口
  • 创建一个可以复用的类,该类可以与其他不相关的类或不可预见的两位协同工作
  • 想使用一个已经存在的子类,但不可能对每一个都进行子类化以匹配他们的接口,对象适配器可以适配它的父类接口
3.2 桥接模式

意图

将抽象部分与其实现部分分离,使他们都可以独立地变化。它是用组合关系代替继承关系来事项,从而降低了抽象和实现这两个可变维度的耦合度

主要角色:

  • 抽象化角色:定义抽象类,并包含一个对实现化对象的引用
  • 扩展抽象化角色:是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法,并通过组合关系调用实现化角色中的业务方法
  • 实现化角色:定义实现化角色的接口,供扩展抽象化角色调用
  • 具体实现化角色:给出实现化角色接口的具体实现

比如:

开发一个跨平台视频播放器,可以在不同操作系统平台(Windows、Mac、Linux)上播放多种格式的视频文件,常见的视频格式包括RMVB、AVI、WMV等。该播放器包含了两个维度,适合使用桥接模式。桥接模式提高了系统的可扩充性,在两个维度,都不需要修改原有系统。
如:如果还有一种视频文件类型wmv,我们只需要再定义一个类实现VideoFile接口即可

优点:

  • 提高了系统的可扩扩充性
  • 实现细节对客户透明

题目描述:

  • 类的抽象和其实现之间不希望有一个固定的绑定关系
  • 不希望在抽象和它的实现部分之间有一个固定的绑定关系
  • 都给另一个对象提供了一定程度上的间接性,都涉及从自身以外的一个接口向这个对象转发请求
  • 类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充
  • 对一个抽象的实现部分的修改应对客户不产生影响,即客户代码不必重新编译
  • 想对客户完全隐藏抽象的实现部分
  • 有许多类要生成的类层次结构
  • 想在多个对象间共享实现,但同时要求客户并不知道这一点

使用场景:

  • 当一个类存在两个独立变化的维度,且两个维度都需要进行扩展时
  • 当一个系统不希望使用继承或因为多层次继承导致系统类的个数急剧增加时
  • 当一个系统需要再构建的抽象化角色和具体化角色之间增加更加的灵活性时,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使他们在抽象层建立一个关联关系
3.3 组合模式

意图

将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性

主要角色:

  • 抽象根节点:定义系统各个层次对象的共有方法和属性,可以预先定义一些默认行为和属性
  • 树枝节点:定义树枝节点的行为,存储子节点,组合树枝节点和叶子节点形成一个树形结构
  • 叶子节点:叶子节点对象,其下再无分支,是系统层次遍历的最小单位

比如:

树形结构的文件夹系统

优点:

  • 组合模式可以清楚地定义分层次的复杂对象,表示对象的全部或部分分层次,它让客户忽略了层次的差异,方便对整个层次结构进行控制
  • 客户端可以一致地使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了客户端代码
  • 在组合模式中增加新的树枝节点和叶子节点都很方便,无需对现有类库进行任何修改,符合“开闭原则”
  • 组合模式为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子节点和树枝节点的递归组合,可以形成复杂的树形结构,但对树形结构的控制却非常简单

题目描述:

  • 表示对象的部分-整体层次结构

组合模式正是应树形结构而生,所以组合模式出现在树形结构的地方,比如:文件目录显示,多级目录呈现等树形结构数据的操作

3.4 装饰器模式

意图

动态地给一个对象添加一些额外的职责,就增加功能而言,装饰器模式比生成子类更加灵活

指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式

主要角色:

  • 抽象构件角色:定义一个抽象接口以规范准备接收附加责任的对象
  • 具体构件角色:实现抽象构件,通过装饰角色为其添加一些职责
  • 抽象装饰角色:继承或实现抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能
  • 具体装饰角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任

题目描述:

  • 将一个对象加以包装以提供一些额外的行为
  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责
  • 动态地给一个对象添加一些额外的职责
  • 处理那些可以撤销的职责
  • 当不能采用生成子类的方式进行扩充时。一种情况是,可能有大量独立地扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是,由于类定义被隐藏,或类定义不能用于生成子类。
3.5 外观模式

意图

为子系统中的一组接口提供一个一致的界面,外观模式定义的一个高层接口,这个接口是使得这一子系统更加任意使用

主要角色:

  • 外观角色:为多个子系统对外提供一个共同的接口
  • 子系统角色:实现系统的部分功能,客户可以通过外观角色访问它

比如:

智能家电控制:

将打开灯、打开电视、打开空调、关灯、关电视、关空调等操作通过智能音箱语音控制

优点:

  • 降低了子系统与客户端之间的耦合度,使得子系统的变化不会影响用它的客户类
  • 对客户屏蔽了子系统组件,减少了客户处理的对象数目,并使得子系统使用起来更加容易

缺点:

  • 不符合开闭原则,修改麻烦

题目描述:

  • 将一系列对象加以包装以简化其接口
  • 需要为一个复杂子系统提供一个简单接口
  • 客户程序与抽象类的实现部分之间存在很大的依赖性,引入外观模式将这个子系统与客户以及其他的子系统分离,可以提高子系统的独立性和可移植性
  • 当需要构建一个层次结构的子系统时,使用外观模式定义子系统中每层的入口点,如果子系统之间是相互依赖的,则可以让他们仅通过外观模式进行通信,从而简化了他们之间的依赖性

使用场景:

  • 对分层结构系统构建时,使用外观模式定义子系统中每层的入口点可以简化子系统之间的依赖关系
3.6 享元模式

意图

运用共享技术有效地支持大量细粒度的对象,从而提高系统资源的利用率

享元模式中存在两种状态:

  • 内部状态,不会随环境的改变而改变的可共享部分
  • 外部状态,随环境改变而改变的不可以共享的部分

主要角色:

  • 抽象享元角色
  • 具体享元角色:为每一个具体享元提供唯一的享元对象
  • 非享元角色
  • 享元工厂角色

比如:

俄罗斯方块:

有不同的颜色和形状(不同颜色为外部状态)

题目描述:

  • 因使用大量的对象而造成很大的存储开销时,进行对象共享,以减少对象数量从而达到较少的内存占用并提升性能
  • 一个应用程序使用了大量的对象
  • 完全由于使用大量的对象,造成很的的存储开销
  • 对象的大对数状态都可变成为外部状态
  • 如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象
3.7 代理模式

意图

为其他对象提供一种代理以控制对这个对象的访问

由于某些原因需要给某对象提供一个代理以控制对该对象的访问,这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介

主要角色:

  • 抽象主题类:通过接口或则抽象类声明真实主题和代理对象实现的业务方法
  • 真实主题类:实现了抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象
  • 代理类:提供了与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制、或扩展真实主题的功能

比如:

火车站买票:

如果要买火车票的话需要去火车站买票,坐车到火车站,排队等一系列的操作,显然比较麻烦,而火车站在多个地方都有售票点,我们去代售点买票就方便很多

优点:

  • 代理模式在客户端和目标对象之间起到一个中介作用和保护目标对象的作用
  • 代理对象可以扩展目标对象的功能
  • 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度

缺点:

  • 增加了系统的复杂度

题目描述:

  • 将一个对象加以包装以控制对这个兑现的访问

  • 在需要比较通用和复杂的对象指针代替简单的指针时

    • 远程代理,为一个对象在不同地址空间提供局部代表

      将网络通信部分隐藏起来,只暴露给本地服务一个接口,通过该接口即可访问远程服务提供的功能,而不必过多关心通信部分的细节

    • 虚代理,根据需要创建开销很大的对象

    • 保护代理,控制对原始对象的访问,用于对象应该有不同的访问权限的时候

      可以给不同的用户提供不同级别的使用权限

    • 智能引用,取代了简单指针,它在访问对象时执行一些附加操作

  • 为其他对象提供一个代理以控制对这个对象的访问

  • 防火墙代理,当你将浏览器配置成使用代理模式时,防火墙就将你的浏览器的请求转给互联网,当互联网返回响应时,代理服务器再把他转给你的浏览器

3.8 结构型设计模式总结
结构定义关键字
适配器模式(Adapter)将一个类的接口转换成客户希望的另外一个接口,使得原本不相容的接口得以协同工作转换,兼容接口
桥接模式(Bridge)将抽象部分与其实现部分分离,使他们都可以独立地变化抽象和实现分离
组合模式(Composite)将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性整体-部分,树形结构
装饰器模式(Decorator)动态地给一个对象添加一些额外的职责,就增加功能而言,装饰器模式比生成子类更加灵活附加职责
外观模式(Facade)为子系统中的一组接口提供一个一致的界面,外观模式定义的一个高层接口,这个接口是使得这一子系统更加任意使用对外同一接口
享元模式(Flyweight)运用共享技术有效地支持大量细粒度的对象细粒度,共享
代理模式(Proxy)为其他对象提供一种代理以控制对这个对象的访问代理控制

4. 行为型设计模式

4.1 责任链模式

意图

使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止

主要角色:

  • 抽象处理者角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接
  • 具体处理者角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者
  • 客户类角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程

比如:

学生请假,不同的批假天数,找不同的上级领导

优点:

  • 降低了对象之间的耦合度
  • 增强了系统的可扩展性,可以增加请求处理类,满足开闭原则
  • 增强了给对象指派职责的灵活性,当工作流程发生变化,可以动态地改变链内的成员或者修改他们的次序,也可动态地新增或者删除责任
  • 责任链简化了对象之间的连接
  • 责任分担,每个类只需要处理自己该处理的工作,不能处理的传递给下一个对象完成

缺点:

  • 不能保证每个请求一定被处理
  • 对比较长的责任链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响
  • 责任链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于责任链的错误设置而导致系统出错

题目描述:

  • 有多个对象可以处理一个请求,在运行时刻自动确定哪个对象处理
  • 一个客户需要使用一组相关对象
  • 想在不明确指定接受者的情况下想多个对象中的一个提交一个请求
  • 可处理一个请求的对象集合应被动态指定
4.2 命令模式

意图

将一个请求封装为一个对象,从而使得可以用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作

将一个请求封装为一个对象,是发出请求的责任和执行请求的责任分割开,这样两者之间通过命令对象进行沟通,这样方便将命令对象进行存储、传递、调用、增加和管理。

主要角色:

  • 抽象命令类角色:定义命令接口,声明执行的方法
  • 具体命令角色:具体的命令,实现命令的接口,通常会持有接收者,并调用接收者的功能来完成命令要执行的操作
  • 实现者/接收者角色:接收者,真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能
  • 调用者/请求者角色:要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口

比如:

吃饭点餐,顾客包订单交给服务员,服务员把订单放在订单柜说“订单来了”,厨师根据订单准备餐点

服务员:调用者角色,由他发起命令

厨师:接收者角色,真正命令执行的对象

订单:命令中包含订单

优点:

  • 降低系统的耦合度
  • 增加或删除命令非常方便
  • 可以实现宏命令

缺点:

  • 可能会导致某些系统有过多的具体命令类
  • 系统结构更加复杂

题目描述:

  • 抽象出执行的动作以参数化某对象
  • 将请求封装为对象从而可以使用不同的请求对客户进行参数化
  • 在不同的时刻指定、排列和执行请求
  • 支持修改日志这样当系统崩溃时,这些修改可以被重做一遍

使用场景:

  • 需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互
  • 系统需要支持命令的撤销(undo)操作和恢复(redo)操作
  • 系统需要再不同的时间指定请求、将请求排队和执行请求
4.3 解释器模式(没怎么考)

意图:

给定一个语言,定义他的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子

比如:

加减法运算,规则为:由数值和±符号组成的合法序列

题目描述:

  • 有一个语言需要解释执行,并且可将句子表示为一个抽象语法树
  • 当有一个语言需要解释执行,并且可将该语言中的句子表示为一个抽象语法树时
4.4 迭代器模式

意图:

提供一种方法顺序访问一个聚合对象中的各个元素,且不需要暴露该对象的内部表示

主要角色:

  • 抽象聚合角色:定义存储、添加、删除聚合元素以及创建迭代器对象的接口
  • 具体聚合角色:实现抽象聚合类,返回一个具体迭代器的实例
  • 抽象迭代器角色:定义访问和遍历聚合元素的接口,通常包含hasNext()、next()等方法
  • 具体迭代器角色:实现抽象迭代器接口中定义的方法,完成聚合对象的遍历,记录遍历的当前位置

题目描述:

  • 访问一个聚合对象的内容而无需暴露它的内部细节的表示
  • 支持对聚合对象的多种遍历
  • 为遍历不同的聚合结构提供一个统一的接口
4.5 中介者模式

意图:

用一个中介对象来封装一系列的对象交互,中介者使各个对象不需要显式的互相引用,从而使其耦合松散,而且可以独立地改变他们之间的交互

比如:

同事类之间的关系比较复杂,是一个网状结构,而引入中介者模式,那么同事类之间的关系将变为星型结构

主要角色:

  • 抽象中介角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法
  • 具体中介者角色:实现中介者接口,定义一个List来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色
  • 抽象同事类角色:定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能
  • 具体同事类角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互

比如:

房屋中介,房主将房屋托管给房屋中介,而租房者从房屋中介获取房屋信息

优点:

  • 松散耦合
  • 集中控制交互
  • 一对多关联变成一对一关联

缺点:

  • 当同事类太多时,中介者的职责将很大,它会变复杂而庞大,以至于系统难以维护

题目描述:

  • 一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象
  • 一组对象以定义良好但是复杂的方式进行通信,产生的相互依赖关系结构混乱且难以理解
  • 减少多个对象或类之间的通信复杂性
  • 中介模式和观察者模式是相互竞争的模式,差别:前者的中介对象封装了其他对象间的通信,而后者通过引入其他对象来分布通信
  • 欲使一个后端数据模型能够被多个前端用户界面连接
4.6 备忘录模式

意图:

在不破坏封装性的前提下捕获一个对象的内部状态,并在对象之外保存这个状态。这样以后就可以将对象恢复到原先保存的状态

优点:

  • 提供了一种可以恢复状态的机制,当用户需要时能够比较方便地将数据恢复到某个历史的状态
  • 实现了内部状态的封装,除了创建它的发起人之外,其他对象都不能访问这些状态信息
  • 简化了发起人类,发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,这符合单一职责原则

缺点:

  • 资源消耗大,如果要保存的内部状态信息过多或者特别频繁,将会占用较大的内存资源

题目描述:

  • 将对象的状态恢复到先前的状态
  • 在不破坏封装性的前提下,捕获对象的内部状态并在对象之外保存
  • 必须保存一个对象在某一个时刻的(部分)状态
  • 如果一个用接口来让其他对象之间得到这些状态,将会暴露对象的实现细节并破坏对象的封装性
4.7 观察者模式

意图:

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新

比如:

使用微信公众号,公众号有内容更新的话,会推送给关注公众号的微信用户端

题目描述:

  • 当一个对象必须通知其他对象,而它又不能假定其他对象时谁时
  • 在发布-订阅消息模型中,订阅者订阅一个主题后,当该主题有新消息到达时,所要订阅者都会受到通知
  • 使所要交互的对象尽量松耦合
  • 当一个对象的改变需要改变其它对象
4.8 状态模式

意图:

允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类

对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时,改变其行为

比如:

通过按钮控制一个电梯的状态,有开门状态,关门状态,停止状态,运行状态。每一种状态改变,都有可能要根据其他状态来更新处理
比如如果电梯处于运行状态,就不能进行开们操作,而电梯是停止状态,就可以执行开门操作

题目描述:

  • 一个对象的行为决定于它的状态,并且它必须在运行时刻根据状态改变它的行为
  • 一个对象在其内部状态改变时改变其行为
  • 一个对象的行为决定于它的状态,并且它必须在运行时刻根据状态改变它的行为
  • 一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态
4.9 策略模式

意图:

定义一系列的算法,把他们一个个封装起来,并且使他们可以相互替换。此模式使得算法可以独立于使用他们的客户而变化

比如:

我们要去旅游选择出行方式,可以选择骑自行车,坐汽车,坐火车,坐飞机

优点:

  • 策略模式之间可以自由切换,由于策略类都实现同一个接口,所以使他们之间可以自由切换
  • 易于扩展,增加一个新的策略只需要添加一个具体的策略类,基本不需要改变原有的代码,符合“开闭原则”
  • 避免使用多重条件选择语句,充分体现面向对象设计思想

缺点:

  • 客户端必须知道所有的策略类,并且自行决定使用哪一个策略类
  • 策略模式将造成产生很多策略类

题目描述:

  • 需要使用一个算法的不同变体
  • 许多相关的类仅仅是行为有异
  • 在设计某购物中心的收银软件系统时,要求能够支持在不同时期推出打折,返利,满减等不同促销活动
  • 一个类定义了多种行为,并且这些行为在这个类的操作以多个条件语句的形式出现
4.10 访问者模式

意图:

封装一些作用于某对象结构中的各元素的操作。它允许在不改变各元素的类的前提下定义作用于这些元素的新操作

比如:

有很多宠物,狗、猫等,要给宠物喂食的话,主人可以喂食,其他人也可以喂食

题目描述:

  • 一个对象结构包含很多类对象,它们有不同的接口,而用户想对这些对象实施一些依赖于其具体类的操作
  • 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而又想避免这些操作“污染”这些对象的类
  • 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作
4.11 模版方法模式(下午题不考)

意图:

定义一个操作中的算法骨架,而将一些步骤延迟到子类中,模版方法模式使得子类可以不改变一个算法结构即可重定义该算法的某些特定步骤

题目描述:

  • 一次性实现一个算法的不变部分,并将可变的行为留给子类来实现
  • 各子类中公共的行为应被提取出来并集中到一个公共父类中,以避免代码重复
  • 控制子类扩展
4.12 行为性设计模式总结
行为型设计模式定义关键字
职责链模式(Chain of Responsibility)(责任链模式)使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止传递请求,职责,链接
命令模式(Command)将一个请求封装为一个对象,从而使得可以用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作参数化,日志记录
解释器模式(Interpreter)给定一个语言,定义他的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子文法,解释
迭代器模式(Iterator)提供一种方法顺序访问一个聚合对象中的各个元素,且不需要暴露该对象的内部表示顺序访问
中介者模式(Mediator)用一个中介对象来封装一系列的对象交互,中介者使各个对象不需要显式的互相引用,从而使其耦合松散,而且可以独立地改变他们之间的交互不直接引用
备忘录模式(Memento)在不破坏封装性的前提下捕获一个对象的内部状态,并在对象之外保存这个状态。这样以后就可以将对象恢复到原先保存的状态保存,恢复
观察者模式(Observer)定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新通知,自动更新
状态模式(State)允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类状态变成类
策略模式(Strategy)定义一系列的算法,把他们一个个封装起来,并且使他们可以相互替换。此模式使得算法可以独立于使用他们的客户而变化算法替换
模版方法模式(Template Method)定义一个操作中的算法骨架,而将一些步骤延迟到子类中,模版方法模式使得子类可以不改变一个算法结构即可重定义该算法的某些特定步骤
访问者模式(Visitor)封装一些作用于某对象结构中的各元素的操作。它允许在不改变各元素的类的前提下定义作用于这些元素的新操作新操作

http://www.ppmy.cn/news/1460931.html

相关文章

HIVE调优-数据倾斜优化(详细版)

HIVE调优-数据倾斜优化 目录 HIVE调优-数据倾斜优化 1.排序优化 1)order by 2)distribute by sort by 3)cluster by语句: 2.数据倾斜优化 1)原因: 2)表现: 3&#xff09…

蓝桥杯国赛每日一题:献给阿尔吉侬的花束(BFS)

题目描述: 阿尔吉侬是一只聪明又慵懒的小白鼠,它最擅长的就是走各种各样的迷宫。 今天它要挑战一个非常大的迷宫,研究员们为了鼓励阿尔吉侬尽快到达终点,就在终点放了一块阿尔吉侬最喜欢的奶酪。 现在研究员们想知道&#xff0…

python从零开始学习深度学习01——神经网络反向传播的链式求导

自我介绍 最懂保险的算法工程师,致力于保险理念的推广,让每个程序员在35岁时都能够免除后顾之忧。通过构建保险组合,避免中年因病致穷,苦攒多年积蓄全部花费在医疗上,因此返贫。有兴趣的朋友后台私信加V:A…

使用 GPT-4-turbo+Streamlit+wiki+calculator构建Math Agents应用【Step by Step】

💖 Brief:大家好,我是Zeeland。Tags: 大模型创业、LangChain Top Contributor、算法工程师、Promptulate founder、Python开发者。📝 CSDN主页:Zeeland🔥📣 个人说明书:Zeeland&…

Java入门基础学习笔记22——程序流程控制

程序流程控制:控制程序的执行顺序。 程序有哪些执行顺序? 顺序、分支和循环。 分支结构: if、switch 循环: for、while、do-while 顺序结构是程序中最简单最基本的流程控制,没有特定的语法结构,按照代码…

MySQL中逗号分隔字段查询方法

MySQL中逗号分隔字段查询 select * FROM th_work_gand_up where FIND_IN_SET(11,lane_code) ; select * from th_work_gand_up where lane_code regexp (^|,)(11|1)(,|$);

21、Flink 的 Checkpoints 使用介绍

Checkpoints 1.概述 Checkpoint 使 Flink 的状态具有良好的容错性,通过 checkpoint 机制,Flink 可以对作业的状态和计算位置进行恢复。 2.Checkpoint 存储 Flink 开箱即用地提供了两种 Checkpoint 存储类型: JobManagerCheckpointStorag…

Python笔记:Python的小括号、中括号和大括号

Python语言最常见的括号有三种:小括号也叫圆括号( )、中括号[ ]和大括号也叫做花括号{ }。 1、小括号( ):代表tuple元组数据类型 Python笔记:数据类型-元组-CSDN博客 2、中括号[ ]:代表list列表数据类型 Python笔记&#xff1a…

区块链的跨链交互:从学校间交流看跨链技术

区块链是一种去中心化的分布式账本技术,它通过加密学和共识机制来确保数据的安全性和不可篡改性。每个区块链就像一所独立的学校,有自己的制度、学生和重点专业。它们各自运行,有时在同一领域展开不同的活动。随着区块链技术的不断发展&#…

标准输入输出流(中北大学-程序设计基础(2))

目录 题目 源码 结果示例 题目 输入三角形的三边a,b,c,计算三角形的面积。形成三角形的条件是ab>c,bc>a,ac>b,编写程序,输入a,b,c,检查a,b,c是否满足以上条件,如不满足,由cerr输出有关出错信息…

鸿蒙内核源码分析(gn应用篇) | gn语法及在鸿蒙的使用

gn是什么? gn 存在的意义是为了生成 ninja,如果熟悉前端开发,二者关系很像 Sass和CSS的关系. 为什么会有gn,说是有个叫even的谷歌负责构建系统的工程师在使用传统的makefile构建chrome时觉得太麻烦,不高效,所以设计了一套更简单,更高效新的构建工具gnninja,然后就被广泛的使用…

基于python的大麦网自动抢票工具的设计与实现

基于python的大麦网自动抢票工具的设计与实现 Design and Implementation of Da Mai Net Ticket Grabbing tool based on Python 完整下载链接:基于python的大麦网自动抢票工具的设计与实现 文章目录 基于python的大麦网自动抢票工具的设计与实现摘要第一章 引言1.1 研究背景…

信息系统项目管理师(高项)--学习笔记【第4章:信息系统管理】

目录 第4章 信息系统管理4.1 管理方法4.1.1管理基础4.1.2规划和组织4.1.3设计和实施4.1.4运维和服务4.1.5优化和持续改进(基于有效的变更管理) 4.2 管理要点4.2.1数据管理4.2.2运维管理4.2.3信息安全管理 第4章 信息系统管理 4.1 管理方法 4.1.1管理基础 3层架构&#xff08…

第十一章数据仓库和商务智能

单选题 (每题1分,共26道题) 1、 [单选] 数据仓库建设的主要驱动力 A:整合数据、减少冗余和提高信息一致性 B:运营支持职能、合规需求和商务智能活动 C:数据集成、分析应用和决策支持 D:客户和消费者的剧增、分析的需求、企业统一管控的需求 正确答案:B 你的答案:B 解…

DHCP原理

什么是DHCP DHCP (Dynamic Host Configuration Protocol,动态主机配置协议)是由Internet工作任务小组设计开发的,专门用于为TCP/IP网络中的计算机自动分配TCP/IP参数的协议,是一个应用层协议,使用UDP的67和68端口。 DHCP的前身是B…

leetcode 2606.找到最大开销的子字符串

思路:dp 这道题是不是很像最大子数组和那道题呢?从这里我们其实能看出来一类题的蹊跷规律来: 也就是说,在涉及到子字符串,子数组这样的字眼的时候,并且有最值问题,我们可以基本上确定是动态规划&#xf…

SSH 免密登录,设置好仍然需要密码登录解决方法

说明: ssh秘钥登录设置好了,但是登录的时候依然需要提供密码 查看系统安全日志,定位问题 sudo cat /var/log/auth.log或者 sudo cat /var/log/secure找到下面的信息 Authentication refused: bad ownership or modes...(网上的…

websevere服务器从零搭建到上线(三)|IO多路复用小总结和服务器的基础框架

文章目录 epollselect和poll的优缺点epoll的原理以及优势epoll 好的网络服务器设计Reactor模型图解Reactor muduo库的Multiple Reactors模型 epoll select和poll的优缺点 1、单个进程能够监视的文件描述符的数量存在最大限制,通常是1024,当然可以更改数…

debootstrap构建基于Debian的嵌入式系统的rootfs

嵌入式芯片:iMX6ULL 准备环境: 确保您的开发机器已安装debootstrap和qemu-user-static(如果您在非ARM机器上构建ARM rootfs)。 sudo apt-get updatesudo apt-get install debootstrap qemu-user-static使用debootstrap创建rootf…

iOS 音量键拍照(延时拍照)

写在前面 下面有两种方法可以实现,一种简单,一种复杂,简单的方法曾经遇到过无法实现的问题,目前不确定为什么。 这是复杂实现的demo,使用很简单,就不做文字解释了 一. 思路 首先需要监听音量键的点击&a…