行为型模式(下)

本文介绍了行为型模式,其用于描述程序运行时复杂流程控制,涉及多对象协作。详细阐述了观察者、中介者、迭代器、访问者、备忘录和解释器六种模式,包括概念、优缺点、结构、应用场景及拓展等内容,是作者参考整理的笔记。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配

一、观察者模式

1. 概念
1)观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式
2. 优缺点
1)优点

	(1)降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系

	(2)目标与观察者之间建立了一套触发机制	

2)缺点

	(1)目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用

	(2)当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率
3. 模式的结构
1)抽象主题(Subject)角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法

2)具体主题(Concrete    Subject)角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象

3)抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用

4)具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态	

在这里插入图片描述

4. 应用场景
1)象间存在一对多关系,一个对象的状态发生改变会影响其他对象

2)当一个抽象模型有两个方面,其中一个方面依赖于另一方面时,可将这二者封装在独立的对象中以使它们可以各自独立地改变和复用
5. 拓展
在 Java 中,通过 java.util.Observable 类和 java.util.Observer 接口定义了观察者模式,只要实现它们的子类就可以编写观察者模式实例

1)Observable类: 是抽象目标类,它有一个 Vector 向量,用于保存所有要通知的观察者对象,下面来介绍它最重要的 3 个方法	

	(1)void addObserver(Observer o) 方法:用于将新的观察者对象添加到向量中

	(2)void notifyObservers(Object arg) 方法:调用向量中的所有观察者对象的 update。方法,通知它们数据发生改变。通常越晚加入向量的观察者越先得到通知

	(3)void setChange() 方法:用来设置一个 boolean 类型的内部标志位,注明目标对象发生了变化。当它为真时,notifyObservers() 才会通知观察者

2)Observer 接口	

	(1)Observer 接口是抽象观察者,它监视目标对象的变化,当目标对象发生变化时,观察者得到通知,并调用 void update(Observable o,Object arg) 方法,进行相应的工作

二、中介者模式

1. 概念
(1)中介者(Mediator)模式的定义:定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。中介者模式又叫调停模式,它是迪米特法则的典型应用
2. 优缺点
1)优点

	(1)降低了对象之间的耦合性,使得对象易于独立地被复用

	(2)将对象间的一对多关联转变为一对一的关联,提高系统的灵活性,使得系统易于维护和扩展

2)缺点

	(1)当同事类太多时,中介者的职责将很大,它会变得复杂而庞大,以至于系统难以维护
3. 模式的结构
1)抽象中介者(Mediator)角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法

2)具体中介者(ConcreteMediator)角色:实现中介者接口,定义一个 List 来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色		

3)抽象同事类(Colleague)角色:定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能

4)具体同事类(Concrete Colleague)角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互

在这里插入图片描述

4. 应用场景
1)当对象之间存在复杂的网状结构关系而导致依赖关系混乱且难以复用时

2)当想创建一个运行于多个类之间的对象,又不想生成新的子类时
5. 扩展
1)不定义中介者接口,把具体中介者对象实现成为单例	

2)同事对象不持有中介者,而是在需要的时候直接获取中介者对象并调用

三、迭代器模式

1. 概念
1)迭代器(Iterator)模式的定义:提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。迭代器模式是一种对象行为型模式
2. 优缺点
1)优点

	(1)访问一个聚合对象的内容而无须暴露它的内部表示

	(2)遍历任务交由迭代器完成,这简化了聚合类

	(3)它支持以不同方式遍历一个聚合,甚至可以自定义迭代器的子类以支持新的遍历

	(4)增加新的聚合类和迭代器类都很方便,无须修改原有代码

	(5)封装性良好,为遍历不同的聚合结构提供一个统一的接口

2)缺点

	(1)增加了类的个数,这在一定程度上增加了系统的复杂性
3. 模式的实现
1)抽象迭代器(Iterator)角色:定义访问和遍历聚合元素的接口,通常包含 hasNext()、first()、next() 等方法

2)具体迭代器(Concretelterator)角色:实现抽象迭代器接口中所定义的方法,完成对聚合对象的遍历,记录遍历的当前位置

3)抽象聚合(Aggregate)角色:定义存储、添加、删除聚合对象以及创建迭代器对象的接口

4)具体聚合(ConcreteAggregate)角色:实现抽象聚合类,返回一个具体迭代器的实例	

在这里插入图片描述

4. 应用场景
1)当需要为聚合对象提供多种遍历方式时

2)当需要为遍历不同的聚合结构提供一个统一的接口时

3)当访问一个聚合对象的内容而无须暴露其内部细节的表示时
5. 扩展
1)迭代器模式常常与组合模式结合起来使用,在对组合模式中的容器构件进行访问时,经常将迭代器潜藏在组合模式的容器构成类中。当然,也可以构造一个外部迭代器来对容器构件进行访问	

四、访问者模式

1. 概念
1)将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式

2)它将对数据的操作与数据结构进行分离,是行为类模式中最复杂的一种模式
2. 优缺点
1)优点

	(1)扩展性好。能够在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能

	(2)复用性好。可以通过访问者来定义整个对象结构通用的功能,从而提高系统的复用程度

	(3)灵活性好。访问者模式将数据结构与作用于结构上的操作解耦,使得操作集合可相对自由地演化而不影响系统的数据结构

	(4)符合单一职责原则。访问者模式把相关的行为封装在一起,构成一个访问者,使每一个访问者的功能都比较单一

2)缺点

	(1)增加新的元素类很困难。在访问者模式中,每增加一个新的元素类,都要在每一个具体访问者类中增加相应的具体操作,这违背了“开闭原则”

	(2)破坏封装。访问者模式中具体元素对访问者公布细节,这破坏了对象的封装性

	(3)违反了依赖倒置原则。访问者模式依赖了具体类,而没有依赖抽象类

3. 模式的结构
1)抽象访问者(Visitor)角色:定义一个访问具体元素的接口,为每个具体元素类对应一个访问操作 visit() ,该操作中的参数类型标识了被访问的具体元素

2)具体访问者(ConcreteVisitor)角色:实现抽象访问者角色中声明的各个访问操作,确定访问者访问一个元素时该做什么

3)抽象元素(Element)角色:声明一个包含接受操作 accept() 的接口,被接受的访问者对象作为 accept() 方法的参数

4)具体元素(ConcreteElement)角色:实现抽象元素角色提供的 accept() 操作,其方法体通常都是 visitor.visit(this) ,另外具体元素中可能还包含本身业务逻辑的相关操作

5)对象结构(Object Structure)角色:是一个包含元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法,通常由 List、Set、Map 等聚合类实现

在这里插入图片描述

4. 应用场景
1)对象结构相对稳定,但其操作算法经常变化的程序

2)对象结构中的对象需要提供多种不同且不相关的操作,而且要避免让这些操作的变化影响对象的结构

3)对象结构包含很多类型的对象,希望对这些对象实施一些依赖于其具体类型的操作 	
5. 拓展
1)与“迭代器模式”联用。因为访问者模式中的“对象结构”是一个包含元素角色的容器,当访问者遍历容器中的所有元素时,常常要用迭代器

2)访问者(Visitor)模式同“组合模式”联用。因为访问者(Visitor)模式中的“元素对象”可能是叶子对象或者是容器对象,如果元素对象包含容器对象,就必须用到组合模式	

五、备忘录模式

1. 概念
(1)备忘录(Memento)模式的定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。该模式又叫快照模式

2. 优缺点
1)优点

	(1)提供了一种可以恢复状态的机制。当用户需要时能够比较方便地将数据恢复到某个历史的状态

	(2)实现了内部状态的封装。除了创建它的发起人之外,其他对象都不能够访问这些状态信息

	(3)简化了发起人类。发起人不需要管理和保存其内部状态的各个备份,所有状态信息都保存在备忘录中,并由管理者进行管理,这符合单一职责原则

2)缺点

	(1)资源消耗大。如果要保存的内部状态信息过多或者特别频繁,将会占用比较大的内存资源
3. 模式的结构
1)发起人(Originator)角色:记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息

2)备忘录(Memento)角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人

3)管理者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改

在这里插入图片描述

4. 应用场景
1)需要保存与恢复数据的场景,如玩游戏时的中间结果的存档功能

2)需要提供一个可回滚操作的场景,如 Word、记事本、Photoshop,Eclipse 等软件在编辑时按 Ctrl+Z 组合键,还有数据库中事务操作
5. 拓展
1)在备忘录模式中,通过定义“备忘录”来备份“发起人”的信息,而原型模式的 clone() 方法具有自备份功能,所以,如果让发起人实现 Cloneable 接口就有备份自己的功能,这时可以删除备忘录类

六、解释器模式

1. 概念
1)解释器(Interpreter)模式的定义:给分析对象定义一个语言,并定义该语言的文法表示,再设计一个解析器来解释语言中的句子。也就是说,用编译语言的方式来分析应用中的实例。这种模式实现了文法表达式处理的接口,该接口解释一个特定的上下文
2. 优缺点
1)优点

	(1)扩展性好。由于在解释器模式中使用类来表示语言的文法规则,因此可以通过继承等机制来改变或扩展文法

	(2)容易实现。在语法树中的每个表达式节点类都是相似的,所以实现其文法较为容易

2)缺点

	(1)执行效率较低。解释器模式中通常使用大量的循环和递归调用,当要解释的句子较复杂时,其运行速度很慢,且代码的调试过程也比较麻烦

	(2)会引起类膨胀。解释器模式中的每条规则至少需要定义一个类,当包含的文法规则很多时,类的个数将急剧增加,导致系统难以管理与维护

	(3)可应用的场景比较少。在软件开发中,需要定义语言文法的应用实例非常少,所以这种模式很少被使用到
3. 模式的结构
1)抽象表达式(Abstract Expression)角色:定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret()

2)终结符表达式(Terminal    Expression)角色:是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应

3)非终结符表达式(Nonterminal Expression)角色:也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式

4)环境(Context)角色:通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值

5)客户端(Client):主要任务是将需要分析的句子或表达式转换成使用解释器对象描述的抽象语法树,然后调用解释器的解释方法,当然也可以通过环境角色间接访问解释器的解释方法

在这里插入图片描述

4. 应用场景
1)当语言的文法较为简单,且执行效率不是关键问题时

2)当问题重复出现,且可以用一种简单的语言来进行表达时

3)当一个语言需要解释执行,并且语言中的句子可以表示为一个抽象语法树的时候,如 XML 文档解释
5. 扩展
1)在项目开发中,如果要对数据表达式进行分析与计算,无须再用解释器模式进行设计了,Java 提供了以下强大的数学公式解析器:Expression4J、MESP(Math Expression String Parser) 和 Jep 等,它们可以解释一些复杂的文法,功能强大,使用简单

参考网址

行为型模式概述(行为型模式的分类)

注:文章是经过参考其他的文章然后自己整理出来的,有可能是小部分参考,也有可能是大部分参考,但绝对不是直接转载,觉得侵权了我会删,我只是把这个用于自己的笔记,顺便整理下知识的同时,能帮到一部分人。
ps : 有错误的还望各位大佬指正,小弟不胜感激

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值