设计者模式4-行为模式

行为模式

模板方法模式

模板方法模式是一种行为设计模式,它定义了一个操作中的算法框架,将一些步骤的具体实现延迟到子类中,以便子类可以重新定义某些步骤的具体行为,同时保持算法流程的一致性。其核心思想是定义一个抽象类,其中包含一个或多个抽象方法和具体方法。抽象方法用于确保子类必须实现某些步骤,而具体方法则提供了实现这些步骤的通用算法框架。

模板方法模式的主要优点包括:

  1. 提高代码复用性:将相同部分代码放在抽象的父类中,避免代码重复。
  2. 提高扩展性:将不同的代码实现在子类中,使得算法的不同部分可以独立变化,提高了系统的灵活性。

然而,该模式也存在一些缺点:

  1. 对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象。
  2. 父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这可能导致一种反向的控制结构,提高了代码阅读的难度。

模板方法模式适用于一次性实现一个算法的不变部分,并将可变部分留给子类实现。此外,当各个子类中公共部分被提取出来,集中到一个公共的父类中,以避免代码重复时,该模式也适用。

在模板方法模式的实现中,需要注意抽象类与具体子类之间的协作,并利用虚函数的多态性技术以及“不用调用我,让我来调用你”的反向控制技术。同时,可以使用继承或回调函数的方式来实现模板方法模式。

总的来说,模板方法模式是一种强大的设计模式,可以在保持算法流程一致性的同时,实现行为的复用和扩展。然而,在使用该模式时,需要仔细考虑其优缺点,并根据具体需求来决定是否采用。

策略模式

策略模式是一种行为型设计模式,它定义了一系列的算法,并将每一个算法封装起来,使它们可以互相替换。策略模式使得算法可以独立于使用它的客户而变化。这主要通过将算法的使用与其实现分离来达成。

策略模式主要由三部分组成:

  1. 抽象策略(Strategy)角色:这是一个抽象角色,通常是一个接口或者抽象类,定义了一个公共行为,以约束一系列的具体策略类。
  2. 具体策略(Concrete Strategy)角色:包装了相关的算法和行为,实现了抽象策略角色所定义的接口,完成具体的业务逻辑。
  3. 环境(Context)角色:持有一个策略类的引用,最终给客户端调用。它针对抽象策略角色编程,将客户端的请求委托给具体的策略对象来执行。

策略模式的主要优点包括:

  1. 算法和使用分离:算法内容的调整不影响使用,两者独立变化。
  2. 易于扩展:新的算法只需要实现新的类,不需要对原有的框架进行修改,符合开闭原则。
  3. 避免多重条件选择:多重条件转移语句不易维护,策略模式可以避免这种情况。
  4. 算法可复用:策略模式将算法封装为独立的类,可以方便地复用。

然而,策略模式也有一些缺点:

  1. 客户端必须知道所有的策略类,并自行决定使用哪一种策略类。这意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。
  2. 策略模式会造成很多的策略类,每个具体策略类都会产生一个新类。有时候可以通过把依赖于环境的状态保存到客户端里面,而将策略类设计成可共享的,这样策略类实例可以被不同客户端使用。

策略模式通常适用于以下场景:

  1. 许多相关的类仅仅是行为有异。
  2. 需要使用一个算法的不同变体。
  3. 算法使用客户不应该知道的数据。
  4. 一个类定义了多种行为,并且这些行为在类的操作中以多个条件语句的形式出现。

总的来说,策略模式是一种非常灵活和强大的设计模式,它可以帮助我们管理一组相关的算法,并使得算法的使用和实现可以独立变化。然而,在使用策略模式时,我们也需要注意其潜在的缺点,并根据实际情况来评估其适用性。

命令模式

命令模式是一种行为设计模式,它将请求或操作封装成一个包含有关请求所有信息的独立对象。这个转换允许将请求作为方法参数传递,延迟或排队请求的执行,并支持可撤销的操作,从而实现将请求者和接收者解耦。

命令模式的主要优点包括:

  1. 降低系统的耦合度:请求者与接收者之间不存在直接引用,因此请求者与接收者之间实现完全解耦。相同的请求者可以对应不同的接收者,同样,相同的接收者也可以供不同的请求者使用,两者之间具有良好的独立性。
  2. 易于扩展:新的命令可以很容易地加入到系统中,增加新的具体命令类不会影响到其他类,因此增加新的具体命令类很容易,无须修改原有系统源代码,甚至客户类代码,满足“开闭原则”的要求。
  3. 易于设计命令队列或宏命令:可以很容易地设计一个命令队列或宏命令(组合命令)。
  4. 提供撤销和恢复操作方案:为请求的撤销(Undo)和恢复(Redo)操作提供了一种设计和实现方案。

然而,命令模式也有一些缺点,例如:

  1. 可能导致系统有过多的具体命令类:如果每个请求都对应一个命令类,那么可能会导致系统中的具体命令类数量过多,从而增加了系统的复杂性。

命令模式通常适用于以下场景:

  1. 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
  2. 请求调用者无需知道接收者的存在,也无需知道接收者是谁。
  3. 系统需要支持命令的撤销、恢复操作,可以将命令对象存储起来。

命令模式是一种强大且灵活的设计模式,它可以帮助我们实现请求者和接收者的解耦,支持命令的排队和撤销等操作,提高系统的可扩展性和可维护性。然而,在使用时也需要注意其可能带来的系统复杂性增加的问题。

责任链模式

责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它将链中的每个节点看作一个对象,每个节点处理的请求均不同,且内部自动维护下一个节点的对象引用。当一个请求从链式的首端发出时,会沿着责任链预设的路径依次传递到每一个节点对象,直到被链中的某个对象处理为止。责任链模式的本质是解耦请求与处理,让请求在处理链中能进行传递与处理。

该模式的主要优点包括:

  1. 解耦:请求发起者和请求响应者进行解耦,链的创建由使用者(客户端)创建。
  2. 链路结构灵活:可以通过改变链路结构动态的新增或删减责任。
  3. 易扩展:可以根据需要增加新的请求处理类,满足开闭原则。
  4. 责任分担:每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
  5. 简化连接:每个对象只保持一个指向其后继者的引用,避免了使用众多的if或者if…else语句。

然而,责任链模式也存在一些缺点:

  1. 性能问题:如果责任链太长或者处理时间过长,会影响整体性能。
  2. 死循环风险:如果节点对象存在循环引用时,会造成死循环,导致系统崩溃。

在实际应用中,责任链模式可以用于多种场景,如用户认证和授权、日志记录、异常处理等。在这些场景中,可以将处理逻辑封装到多个处理器中,并按照一定的顺序组成一个责任链。当需要处理请求时,请求会沿着责任链传递,每个处理器可以选择是否处理该请求,以及如何处理。

总的来说,责任链模式是一种强大的设计模式,可以帮助我们更好地处理复杂的请求处理流程,但也需要在使用时注意其可能带来的性能问题和死循环风险。

状态模式

状态模式是一种行为型设计模式,它允许一个对象在其内部状态改变时改变它的行为。该模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况。通过把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。

状态模式将状态封装成独立的类,并将对状态的行为委托给当前状态对象。当对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,状态模式特别有用。此外,当一个对象有多个状态,并且状态之间存在复杂的转换逻辑时,状态模式可以简化代码和提高可维护性。

状态模式的主要优点包括:

  1. 封装了状态的转换规则,使得状态转换代码更加集中和易于管理。
  2. 将与某个状态有关的行为放到一个类中,只需注入不同的状态对象即可使环境对象拥有不同的行为。
  3. 允许状态转换逻辑与状态对象合成一体,避免了使用庞大的条件语句来将业务方法和状态转换代码交织在一起。

然而,状态模式也存在一些缺点:

  1. 如果一个事物具备很多状态,则会造成状态类太多,导致系统复杂。
  2. 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
  3. 状态模式对“开闭原则”的支持并不太好,增加新的状态类可能需要修改那些负责状态转换的源代码,否则无法切换到新增状态。

总的来说,状态模式在特定场景下非常有用,但在使用时需要权衡其优缺点,并确保正确应用以避免潜在的复杂性和修改难题。

观察者模式

观察者模式是一种对象行为模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。在观察者模式中,主体是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅并接收通知。

观察者模式有许多应用场景,包括但不限于:

  1. 事件处理机制:用于处理事件驱动的编程,事件触发时,事件源对象会通知事件处理程序(观察者)以执行相应的操作。
  2. 实时数据更新:在需要实时更新数据的应用中,观察者模式可以用于将数据源与数据消费者连接起来,当数据源的数据发生变化时,观察者可以自动获取最新的数据并进行处理。
  3. 消息队列系统:观察者模式可用于消息队列系统,其中生产者将消息发送到队列,而消费者作为观察者订阅队列以接收和处理消息。
  4. 股票市场监测:股票市场应用程序可以使用观察者模式来监测股票价格变化,并将这些变化通知给投资者。

此外,观察者模式具有以下优点:

  1. 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。
  2. 观察者模式在观察目标和观察者之间建立一个抽象的耦合,观察目标只需要维持一个抽象观察者的集合,无须了解其具体观察者。
  3. 观察者模式支持广播通信,观察目标会向所有已注册的观察者对象发送通知,简化了一对多系统设计的难度。

然而,观察者模式也存在一些缺点:

  1. 当观察者对象很多时,通知的发布会花费很长时间,影响程序的效率。
  2. 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅是知道观察目标发生了变化。
  3. 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。

在使用观察者模式时,需要注意具体目标对象和具体观察者对象之间不能直接调用,否则会使两者之间紧密耦合起来,这违反了面向对象的设计原则。

总的来说,观察者模式是一种强大且灵活的设计模式,它使得对象之间的依赖关系变得更为清晰和可维护。然而,在使用时也需要考虑其可能带来的性能问题以及循环依赖的风险,并根据具体需求来决定是否采用。

中介者模式

中介者模式(Mediator Pattern)是一种对象行为型设计模式,其定义是:通过一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。中介者模式又叫调停模式,它是迪米特法则的典型应用。

中介者模式的主要优点包括:

  1. 类之间各司其职,符合迪米特法则。
  2. 降低了对象之间的耦合性,使得对象易于独立地被复用。
  3. 将对象间的一对多关联转变为一对一的关联,提高了系统的灵活性,使得系统易于维护和扩展。

然而,中介者模式也存在一些缺点:

  1. 中介者模式将原本多个对象直接的相互依赖变成了中介者和多个同事类的依赖关系。
  2. 当同事类越多时,中介者就会越臃肿,变得复杂且难以维护。

中介者模式主要适用于以下场景:

  1. 系统中对象之间存在复杂的引用关系,系统结构混乱且难以理解。
  2. 一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象。
  3. 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。

在实际应用中,中介者模式可以帮助我们管理对象之间的交互,使得代码更加清晰、易于维护。然而,在使用中介者模式时,我们也需要注意其可能带来的复杂性,特别是当系统中存在大量对象时,中介者可能会变得非常庞大和复杂。因此,在决定是否使用中介者模式时,我们需要权衡其优缺点,并考虑系统的具体情况和需求。

迭代器模式

迭代器模式(Iterator Pattern)是一种对象行为模式,用于提供一种方法顺序访问一个聚合对象(如Java中的集合、数组等)中的各个元素,而无需暴露该对象的内部表示。它支持以不同的方式遍历聚合对象,并简化了聚合类。在同一个聚合对象上,可以有多个遍历方式,且增加新的聚合类和迭代器类都很方便,无需修改原有代码。

迭代器模式的主要优点包括:

  1. 它支持以不同的方式遍历一个聚合对象。
  2. 简化了聚合类。
  3. 在同一个聚合对象上可以有多个遍历。
  4. 提供了统一的接口,如开始、下一个、是否结束、当前哪一项等,使得遍历的操作更加便捷和标准化。

然而,迭代器模式也存在一些缺点:

  1. 由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
  2. 如果程序只与简单的集合进行交互,使用迭代器模式可能会显得过于复杂和繁琐。对于某些集合,如ArrayList,使用迭代器可能比直接遍历的效率低。

总的来说,迭代器模式在需要对聚合对象进行复杂遍历或隐藏其内部实现细节时非常有用。然而,在决定是否使用迭代器模式时,需要权衡其优缺点,并根据具体的应用场景和需求来做出决策。

访问者模式

访问者模式(Visitor Pattern)是GoF提出的23种设计模式中的一种,属于行为模式。该模式定义了一种作用于某对象结构中的各元素的操作,可以在不改变各元素类的前提下定义作用于这些元素的新操作。

访问者模式涉及的角色包括:

  1. Visitor:抽象访问者角色,为该对象结构中具体元素角色声明一个访问操作接口。
  2. ConcreteVisitor:具体访问者角色,实现Visitor声明的接口。
  3. Element:定义一个接受访问操作(accept()),它以一个访问者(Visitor)作为参数。
  4. ConcreteElement:实现了抽象元素(Element)所定义的接受操作接口。
  5. ObjectStructure:结构对象角色,具备枚举元素、提供高层接口以允许访问者访问其元素等特性。

该模式的优点有:

  • 符合单一职责原则,将元素类中与访问者相关的操作集中起来,使得元素类更加专注于其核心职责。
  • 优秀的扩展性,可以通过添加新的访问者来轻松地增加新的操作,而无需修改原有的元素类。

然而,该模式也存在一些缺点:

  • 违反迪米特原则,因为具体元素对访问者公布了内部细节。
  • 增加新的数据结构较为困难,因为该模式将数据结构和操作解耦,导致数据结构的变化可能影响到所有的访问者。

访问者模式适用于以下场景:

  • 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
  • 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。
  • 当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要的操作。

总的来说,访问者模式是一种强大的设计模式,它允许在不修改对象结构的情况下增加新的操作,提高了系统的灵活性和可扩展性。然而,它也有一些局限性,因此在选择是否使用这种模式时,需要根据具体的应用场景和需求进行权衡。

备忘录模式

备忘录模式是一种软件设计模式,属于行为模式,也是GoF提出的23种设计模式之一。它允许在不破坏对象封装性的前提下捕获对象的内部状态,并在需要时将该对象恢复到先前保存的状态。该模式的主要目的是提供一种可以恢复状态的机制,使得用户可以方便地撤销之前的操作或恢复到某个历史的状态。

备忘录模式的核心是设计备忘录类以及用于管理备忘录的管理者类。备忘录类负责保存对象的内部状态,而管理者类则负责创建、存储和管理这些备忘录。发起人(Originator)角色负责记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,并可以访问备忘录里的所有信息。

备忘录模式适用于需要提供保存和恢复数据的相关状态场景,如撤销操作、状态恢复等。例如,在游戏中的存档使用、编辑工具中的“撤销”操作、浏览器中的后退功能等,都可以采用备忘录模式来实现。

备忘录模式的优点包括提供了一种可恢复状态的机制,封装了对象的内部状态,简化了发起人类的设计,并符合单一职责原则。然而,其缺点在于如果保存的内部状态信息过多或特别频繁,将会占用较大的内存资源。

在使用备忘录模式时,需要注意备忘录的声明期,避免在不使用时占用资源。同时,也要认识到备忘录并非万能的“后悔药”,它不能解决所有问题,特别是在处理复杂系统或频繁操作的情况下。因此,在设计系统时,应根据实际需求权衡是否使用备忘录模式。

解释器模式

解释器模式(Interpreter Pattern)是一种行为型设计模式,它定义了一个解释器,用于解释给定语言和文法的句子。其实质是把语言中的每个符号定义成一个(对象)类,从而把每个程序转换成一个具体的对象树。在这种模式下,解释器用于解析和执行语言中的表达式,通过定义语言的文法来表示,并依据这个表示来解释语言中的句子。

解释器模式的优点包括灵活性高,可以通过定义语言的文法和解释器,灵活地扩展和改变语言的解析和执行规则。然而,它也存在一些缺点,比如执行效率可能较低,因为解释器模式通常需要递归调用;同时,当文法规则非常复杂时,解释器模式的类结构可能变得非常复杂,难以维护。

解释器模式在特定类型问题发生频率足够高的情况下非常适用,例如在日志处理中,对于格式不同的服务日志,可以通过解释器模式解析生成报表。在实际应用中,解释器模式可能是开源包,如Express4J, JEP等。

总的来说,解释器模式是一种强大的设计模式,允许对特定语言进行解释和执行。然而,使用此模式时需要权衡其优缺点,并确保在合适的应用场景下使用。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇