7.2 设计模式

设计模式

  • 7.3.1 设计模式的要素
  • 7.3.2 创建型设计模式
  • 7.3.3 结构性设计模式
    • 1. Adapter (适配器)
    • 2. Bridge(桥接)
    • 3.Composite(组合)
    • 4.Decorator(装饰)
    • 5.Facade(外观)
    • 6.Flyweight(享元)
    • 7.Proxy(代理)
    • 8. 结构型模式比较
  • 7.3.4 行为型设计模式
    • 1 Chain of Responsibility [ (责任链模式 )](https://blog.csdn.net/QQ657205470/article/details/143500787)
    • 2 Command [(命令模式)](https://blog.csdn.net/QQ657205470/article/details/143477255)
    • 3 Interpreter [(解释器模式)](https://blog.csdn.net/QQ657205470/article/details/143476560)
    • 4 Iterator [(迭代器模式)](https://blog.csdn.net/QQ657205470/article/details/143410018)
    • 5 Mediator [(中介者模式)](https://blog.csdn.net/QQ657205470/article/details/143406727)
    • 6 Memento [(备忘录模式)](https://blog.csdn.net/QQ657205470/article/details/143406467)
    • 7 Observer [(观察者模式)](https://blog.csdn.net/QQ657205470/article/details/143303340)
    • 8 State [(状态)](https://blog.csdn.net/QQ657205470/article/details/143303294)
    • 9 Strategy [(策略)](https://blog.csdn.net/QQ657205470/article/details/143501594)
    • 10 Template Method [(模板方法)](https://blog.csdn.net/QQ657205470/article/details/143502008)
    • 11 Visitor [(访问者模式)](https://blog.csdn.net/QQ657205470/article/details/143502222)
    • 12 行为模式比较

7.3.1 设计模式的要素

“每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样,你就能一次又一次地使用该方案而不必做重复劳动”。设计模式的核心在于提供了相关问题的解决方案,使得人们可以更加简单方便地复用成功的设计和体系结构。

设计模式一般有以下4个基本要素。
(1)模式名称(Pattemm Name)。一个助记名,它用一两个词来描述模式的问题、解决方案和效果。命名一个新的模式增加了设计词汇。设计模式允许在较高的抽象层次上进行设计。基于一个模式词汇表,就可以讨论模式并在编写文档时使用它们。模式名可以帮助人们思考,便于人们与其他人交流设计思想及设计结果。找到恰当的模式名也是设计模式工作的难点之一。

(2)问题(Problem)。问题描述了应该在何时使用模式。它解释了设计问题和问题存在的前因后果,可能描述了特定的设计问题,如怎样用对象表示算法等;也可能描述了导致不灵活设计的类或对象结构。有时候,问题部分会包括使用模式必须满足的一系列先决条件。(3)解决方案(Solution)。解决方案描述了设计的组成成分、它们之间的相互关系及各自的职责和协作方式。因为模式就像一个模板,可应用于多种不同场合。所以解决方案并不描述一个特定的具体的设计或实现,而是提供设计问题的抽象描述和怎样用一个具有一般意义的元素组合(类或对象组合)来解决这个问题。

(4)效果(Consequences)。效果描述了模式应用的效果及使用模式应权衡的问题。尽管描述设计决策时,并不总提到模式效果,但它们对于评价设计选择和理解使用模式的代价及好处具有重要意义。软件效果大多关注对时间和空间的衡量,它们也表述了语言和实现问题。因为复用是面向对象设计的要素之一,所以模式效果包括它对系统的灵活性、扩充性或可移植性的影响,显式地列出这些效果对理解和评价这些模式很有帮助。
设计模式确定了所包含的类和实例,它们的角色、协作方式以及职责分配。每一个设计模式都集中于一个特定的面向对象设计问题或设计要点,描述了什么时候使用它,在另一些设计约束条件下是否还能使用,以及使用的效果和如何取舍。

按照设计模式的目的可以分为三大类,如表 7-1 所示。

创建型模式与对象的创建有关;结构型模式处理类或对象的组合;行为型模式对类或对象怎样交互和怎样分配职责进行描述。在这里插入图片描述

7.3.2 创建型设计模式

7.3.3 结构性设计模式

结构型设计模式涉及如何组合类和对象以获得更大的结构。结构型类模式采用继承机制来组合接口或实现。一个简单的例子是采用多重继承方法将两个以上的类组合成一个类,结果这个类包含了所有父类的性质。这一模式尤其有助于多个独立开发的类库协同工作。其中一个例子是类形式的 Adapter 模式。一般来说,适配器使得一个接口与其他接口兼容,从而给出了多个不同接口的统一抽象。为此,类适配器对一个 adaptee 类进行私有继承。这样,适配器就可
以用 adaptee 的接口表示它的接口。

结构型对象模式不是对接口和实现进行组合,而是描述了如何对一些对象进行组合,从而实现新功能的一些方法。因为可以在运行时刻改变对象组合关系,所以对象组合方式具有更大的灵活性,而这种机制用静态类组合是不可能实现的。

Composite 模式是结构型对象模式的一个实例。它描述了如何构造一个类层次式结构,这一结构由两种类型的对象所对应的类构成。其中的组合对象使得用户可以组合基元对象以及其他的组合对象,从而形成任意复杂的结构。在Proxy 模式中,proxy 对象作为其他对象的一个方便的替代或占位符。它的使用可以有多种形式,例如可以在局部空间中代表一个远程地址空间中的对象,也可以表示一个要求被加载的较大的对象,还可以用来保护对敏感对象的访问。Proxy 模式还提供了对对象的一些特有性质的一定程度上的间接访问,从而可以限制、增强或修改这些性质。Flyweight模式为了共享对象定义了一个结构。至少有两个原因要求对象共享:效率和一致性。Flyweight 的对象共享机制主要强调对象的空间效率。使用很多对象的应用必须考虑每一个对象的开销。使用对象共享而不是进行对象复制,可以节省大量的空间资源。但是,仅当这些对象没有定义与上下文相关的状态时,它们才可以被共享。Flweight的对象没有这样的状态。任何执行任务时需要的其他一些信息仅当需要时才传递过去。由于不存在与上下文相关的状态,因此 Flyweight 对象可以被自由地共享。

如果说 Flyweight 模式说明了如何生成很多较小的对象,那么 Facade 模式则描述了如何用单个对象表示整个子系统。模式中的facade 用来表示一组对象,facade 的职责是将消息转发给它所表示的对象。Bridge 模式将对象的抽象和其实现分离,从而可以独立地改变它们。Decorator 模式描述了如何动态地为对象添加职责。Decorator 模式是一种结构型模式,这一模式采用递归方式组合对象,从而允许添加任意多的对象职责。例如,一个包含用户界面组件的 Decorator 对象可以将边框或阴影这样的装饰添加到该组件中,或者它可以将窗口滚动和缩放这样的功能添加到组件中。可以将一个

Decorator 对象嵌套在另外一个对象中,就可以很简单地增加两个装饰,添加其他的装饰也是如此。因此,每个Decorator 对象必须与其组件的接口兼容并且保证将消息传递给它。Decorator 模式在转发一条信息之前或之后都可以完成它的工作(例如绘制组件的边框)。许多结构型模式在某种程度上具有相关性。

1. Adapter (适配器)

1)意图

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

2)结构
类适配器使用多重继承对一个接口与另一个接口进行匹配,其结构如图 7-30所示。对象适配器依赖于对象组合,其结构如图7-31所示。
其中:

  • Target 定义 Client 使用的与特定领域相关的接口。
  • Client 与符合 Target 接口的对象协同。
  • Adaptee 定义一个已经存在的接口,这个接口需要适配。
  • Adapter 对 Adaptee 的接口与 Target 接口进行适配。
    在这里插入图片描述
    3)适用性
    Adapter 模式适用于:
  • 想使用一个已经存在的类,而它的接口不符合要求。
  • 想创建一个可以服用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。
  • (仅适用于对象 Adapter)想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。

2. Bridge(桥接)

1)意图

将抽象部分与其实现部分分离,使它们都可以独立地变化。

2)结构
桥接模式的结构如图 7-32 所示。
在这里插入图片描述
其中:

  • Abstraction 定义抽象类的接口,维护一个指向 Implementor 类型对象的指针。
  • RefinedAbstraction 扩充由Abstraction 定义的接口。
  • Implementor 定义实现类的接口,该接口不一定要与 Abstraction 的接口完全一致;事实上这两个接口可以完全不同。一般来说,Implementor 接口仅提供基本操作,而Abstraction 定义了基于这些基本操作的较高层次的操作。
  • Concretelmplementor 实现 Implementor 接口并定义它的具体实现。

3)适用性
Bridge 模式适用于:

  • 不希望在抽象和它的实现部分之间有一个固定的绑定关系。例如,这种情况可能是因为,在程序运行时刻实现部分应可以被选择或者切换。
  • 类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充。这是 Bridge 模式使得开发者可以对不同的抽象接口和实现部分进行组合,并分别对它们进行扩充。
  • 对一个抽象的实现部分的修改应对客户不产生影响,即客户代码不必重新编译。
  • (C++)想对客户完全隐藏抽象的实现部分。
  • 有许多类要生成的类层次结构。
  • 想在多个对象间共享实现(可能使用引用计数),但同时要求客户并不知道这一点。

3.Composite(组合)

1)意图

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

2)结构
组合模式的结构如图 7-33 所示。
在这里插入图片描述
其中:

  • Component 为组合中的对象声明接口;在适当情况下实现所有类共有接口的默认行为;声明一个接口用于访问和管理 Component 的子组件;(可选)在递归结构中定义一个接口,用于访问一个父组件,并在合适的情况下实现它。
  • Leaf在组合中表示叶结点对象,叶结点没有子结点:在组合中定义图元对象的行为。
  • Composite 定义有子组件的那些组件的行为;存储子组件;在Component 接口中实现与子组件有关的操作。
  • Client 通过 Component 接口操纵组合组件的对象。

3)适用性
Composite 模式适用于:

  • 想表示对象的部分-整体层次结构。
  • 希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。

4.Decorator(装饰)

1)意图

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

2)结构
装饰模式的结构如图 7-34 所示。
在这里插入图片描述
其中:

  • Component 定义一个对象接口,可以给这些对象动态地添加职责。
  • ConcreteComponent 定义一个对象,可以给这个对象添加一些职责。Decorator 维持一个指向 Component 对象的指针,并定义一个与 Component 接口一致的接口。
  • ConcreteDecorator 向组件添加职责。

3)适用性
Decorator 模式适用于:

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

5.Facade(外观)

1)意图

为子系统中的一组接口提供一个一致的界面,Facade 模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

2)结构
外观模式的结构如图 7-35 所示。
在这里插入图片描述
其中:

  • Facade 知道哪些子系统类负责处理请求;将客户的请求代理给适当的子系统对象。
  • Subsystem classes 实现子系统的功能;处理有 Facade 对象指派的任务;没有 Facade 的任何相关信息,即没有指向 Facade 的指针。

3)适用性
Facade 模式适用于:

  • 要为一个复杂子系统提供一个简单接口时,子系统往往因为不断演化而变得越来越复杂。大多数模式使用时都会产生更多更小的类,这使得子系统更具有可重用性,也更容易对子系统进行定制,但也给那些不需要定制子系统的用户带来一些使用上的困难。Facade 可以提供一个简单的默认视图,这一视图对大多数用户来说已经足够,而那些需要更多的可定制性的用户可以越过 Facade 层。
  • 客户程序与抽象类的实现部分之间存在着很大的依赖性。引入Facade 将这个子系统与客户以及其他的子系统分离,可以提高子系统的独立性和可移植性。
  • 当需要构建一个层次结构的子系统时,使用 Facade 模式定义子系统中每层的入口点。如果子系统之间是相互依赖的,则可以让它们仅通过 Facade 进行通信,从而简化了它们之间的依赖关系。

6.Flyweight(享元)

1)意图

运用共享技术有效地支持大量细粒度的对象。

2)结构
享元模式的结构如图 7-36 所示。
在这里插入图片描述
其中:

  • Flyweight 描述一个接口,通过这个接口 Flyweight 可以接受并作用于外部状态
  • ConcreteFlyweight 实现 Flyweight 接口,并为内部状态(如果有)增加存储空间。ConcreteFlywweight 对象必须是可共享的。它所存储的状态必须是内部的,即它必须独立于 ConcreteFlyweight 对象的场景。
  • 并非所有的 Flyweight 子类都需要被共享。Flywweight 接口使共享成为可能,但它并不强制共享。在 Flyweight 对象结构的某些层次,UnsharedConcreteFlyweight 对象通常将ConcreteFlyweight 对象作为子结点。
  • FlyweightFactory 创建并管理 Flyweight 对象;确保合理地共享 Flyweight,当用户请求一个 Flyweight 时,FlyweightFactony 对象提供一个已创建的实例或者在不存在时创建一个实例。
  • Client 维持一个对 Flyweight 的引用;计算或存储一个或多个 Flyweight 的外部状态。

3)适用性
Flyweight 模式适用于:

  • 一个应用程序使用了大量的对象。
  • 完全由于使用大量的对象,造成很大的存储开销。
  • 对象的大多数状态都可变为外部状态。
  • 如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。
  • 应用程序不依赖于对象标识。由于 Flyweight 对象可以被共享,所以对于概念上明显有别的对象,标识测试将返回真值。

7.Proxy(代理)

1)意图

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

2)结构
代理模式的结构如图 7-37 所示。
在这里插入图片描述
其中:

  • Proxy 保存一个引用使得代理可以访问实体;提供一个与 Subiect 的接口相同的接口,使代理可以用来代替实体;控制对实体的存取,并可能负责创建和删除它;其他功能依赖于代理的类型:Remote Proxy 负责对请求及其参数进行编码,并向不同地址空间中的实体发送已编码的请求;Vitial Proxy 可以缓存实体的附加信息,以便延迟对它的访问;Protection Proxy 检查调用者是否具有实现一个请求所必需的访问权限。
  • Subject 定义 RealSubject 和 Proxy 的共用接口,这样就在任何使用 RealSubiect 的地方都可以使用 Proxy。
  • RealSubject 定义 Proxy 所代表的实体。

3)适用性

  • Proxy 模式适用于在需要比较通用和复杂的对象指针代替简单的指针的时候,常见情况有:远程代理(Remote Proxy)为一个对象在不同地址空间提供局部代表。
  • 虚代理(Vital Proxy)根据需要创建开销很大的对象。
  • 保护代理(Protection Proxy)控制对原始对象的访问,用于对象应该有不同的访问权限的时候。
  • 智能引用(Smart Reference)取代了简单的指针,它在访问对象时执行一些附加操作。典型用途包括:对指向实际对象的引用计数,这样当该对象没有引用时,可以被自动释放;当第一次引用一个持久对象时,将它装入内存;在访问一个实际对象前,检查是否已经锁定了它,以确保其他对象不能改变它。

8. 结构型模式比较

Adapter 模式和 Bridge 模式具有一些功能特征,都给另一个对象提供了一定程度上的间接性,因而有利于系统的灵活性,另外都涉及从自身以外的一个接口向这个对象转发请求。Adapte1模式主要是为解决两个已有接口之间不匹配的问题,不考虑这些接口是怎样实现的,也不考虑它们各自可能会如何演化。这种方式不需要对两个独立设计的类中的任何一个进行重新设计,就能够使它们协同工作。Bridge 模式则对抽象接口与它的(可能是多个)实现部分进行桥接。虽然这一模式运行使用者修改实现它的类,但是它仍然为用户提供了一个稳定的接口,也会在系统演化时适应新的实现。Adapter 模式和 Bridge 模式通常被用于软件生命周期的不同阶段,针对不同的问题。Adapter 模式在类已经设计好后实施;而 Bridge模式在设计类之前实施。

Composite 模式和 Decorator 模式具有类似的结构,说明它们都是基于递归组合来组织可变数目的对象。Decorator 旨在能够不需要生成子类即可给对象添加职责,这避免了静态实现所有功能组合而导致子类急剧增加。Composite旨在构造类,使多个相关的对象能够以统一的方式处理,而多重对象可以被当作一个对象来处理,重点在于表示。两者通常协同使用。

Decorator 模式和 Proxy 模式都描述了怎样为对象提供一定程度上的间接引用。Proxy 模式
构成一个对象并为用户提供一致的接口,与 Decorator 模式不同的是,Proxy 模式不能动态地添加或分离性质,也不是为递归组合而设计的,它强调一种关系(Proxy 与它的实体之间的关系),这种关系可以静态地表达。其目的是,当直接访问一个实体不方便或不符合需要时,为这个实体提供一个替代者,例如,实体在远程设备上,访问受到限制或者实体是持久存储的。在 Proxy模式中,实体定义了关键功能,而 Proxy提供(或拒绝)对它的访问。在Decorator 模式中,组件仅提供了部分功能,而一个或多个 Decorator 负责完成其他功能。Decorator 模式适用于编译时不能(至少不方便)确定对象的全部功能的情况。

7.3.4 行为型设计模式

行为模式涉及算法和对象间职责的分配。行为模式不仅描述对象或类的模式,还描述它们之间的通信模式。这些模式刻画了在运行时难以跟踪的、复杂的控制流。它们将用户的注意力
从控制流转移到对象间的联系方式上来。

行为类模式使用继承机制在类间分派行为。本小节包括两个这样的模式。其中Template Method 较为简单和常用。模板方法是一个算法的抽象定义,它逐步地定义该算法,每一步调用一个抽象操作或一个原语操作,子类定义抽象操作以具体实现该算法。另一种行为类模式是Imtenpreter,它将一个文法表示为一个类层次,并实现一个解释器作为这些类的实例上的一个操作。

行为对象模式使用对象复合而不是继承。一些行为对象模式描述了一组对等的对象怎样相互协作以完成其中任一个对象都无法单独完成的任务。这里一个重要的问题是对等的对象。

如何互相了解对方。对等对象可以保持显式的对对方的引用,但那会增加它们的合度。在极端情况下,每一个对象都要了解所有其他的对象。Mediator 在对等对象间引入一个 mediator
对象以避免这种情况的出现。mediator 提供了松耦合所需的间接性。

Chain ofResponsibility 提供更松的耦合。它让用户通过一条候选对象链隐式地向一个对象发送请求。根据运行时刻情况任一候选者都可以响应相应的请求。候选者的数目是任意的,可以在运行时刻决定哪些候选者参与到链中。

Observer 模式定义并保持对象间的依赖关系。典型的 Observer 的例子是 Smalltalk 中的模型/视图/控制器,其中,一旦模型的状态发生变化,型的所有视图都会得到通知。

其他的行为对象模式常将行为封装在一个对象中并将请求指派给它。Stategy 模式将算法封装在对象中,这样可以方便地指定和改变一个对象所使用的算法。Command 模式将请求封装在对象中,这样它就可作为参数来传递,也可以被存储在历史列表中,或者以其他方式使用。State 模式封装一个对象的状态,使得这个对象的状态对象变化时,该对象可改变它的行为。Visitor 封装分布于多个类之间的行为,而 Iterator 抽象了访问和遍历一个集合中的对象的方式。

1 Chain of Responsibility (责任链模式 )

2 Command (命令模式)

3 Interpreter (解释器模式)

4 Iterator (迭代器模式)

5 Mediator (中介者模式)

6 Memento (备忘录模式)

7 Observer (观察者模式)

8 State (状态)

9 Strategy (策略)

10 Template Method (模板方法)

11 Visitor (访问者模式)

12 行为模式比较

很多行为模式注重封装变化。当一个程序的某个方面的特征经常发生改变时,这些模式就定义一个封装这个方面的对象。这样,当该程序的其他部分依赖于这个方面时,它们都可以与此对象协作。这些模式通常定义一个抽象类来描述这些封装变化的对象,并且通常该模式依据这个对象来命名。例如:

  • 一个 Strategy 对象封装一个算法。
  • 一个 State 对象封装一个与状态相关的行为。
  • 一个 Mediator 对象封装对象间的协议。
  • 一个 Iterator 对象封装访问和遍历一个聚集对象中的各个组件的方法。

这些模式描述了程序中很可能会改变的方面。大多数模式有两种对象:封装该方面特征的新对象和使用这些新对象的已有对象。但并非所有的对象行为模式都有这样的分割功能,例如。Chain ofResponsibility 可以处理任意数目的对象(即一个链),而所有这些对象可能已经存在于系统中了。这也说明了行为模式的另一个不同点:并非所有的行为式都定义类之间的静态通信关系。

一些模式引入总是被用作参数的对象。例如 Visitor,一个 Visitor 对象是一个多态的 Accep操作的参数,这个操作作用于该 Visitor 对象访问的对象。其他模式定义一些可作为令牌进行传递的对象,这些对象将在稍后被调用。例如,Command和Memento。在 Command 中,令牌代表一个请求;在 Memento 中,两台代表在一个对象在某个特定时刻的内部状态。在这两种情况下,令牌都可以有一个复杂的内部表示,但客户并不会意识到这一点。另外,在Command 模式中多态特别重要,这是因为执行 Command 对象是一个多态操作。而 Memento接口非常小,以至于备忘录只能作为一个值传递,因此,它很可能根本不给它的客户提供任何多态操作。

Mediator 和 Observer 是相互竞争的模式,它们之间的差别是:Observer 通过引入 Observer和 Subject 对象米分布通信,而 Mediator 对象则封装了其他对象间的通信。Observer 模式中不存在封装一个约束的单个对象,而必须是 Observer 和 Subiect 对象相互协作来维护这个约束。通信模式由 Observer 和 Subject 连接的方式决定:一个 Subject通常有多个 Observer,并且有时一个 Subject 的 Observer 也是另一个 Observer 的日标。Observer 模式有利于 Observer 和 Subiect之间的分割和松耦合,易于产生更细粒度且更易于复用的类。Mediator 模式的目的是集中而不是分布,它将维护一个约束的职责直接放在一个中间者中。

Command、Observer、Mediator 和 Chain ofResponsibility 等模式都涉及如何对发送者和接收者解耦,但各自有不同的权衡考虑。

Command 模式使用一个 Comand 对象来定义一个发送者和一个接收者之间的绑定关系,从而支持解耦。Command 对象提供了一个提交请求的简单接口(即 Execute 操作),将发送者和接收者之间的连接定义在一个对象,使得该发送者可以与不同的接收者一起工作,达到将发送者和接收者解耦,使发送者更易于复用。此外,可以复用Command 对象,用不同的发送者参数化一个接收者。

Observer 模式通过定义一个接口来通知目标中发生的改变,从而将发送者(目标)与接收者(观察者)解耦。Observer 定义了一个比 Command 更松的发送者-接收者绑定,这是因为一个目标可能有多个观察者,并且其数目可以在运行时变化。此模式中的Subiect 和 Observer 接口是为了处理 Subject 的变化而设计的,因此,当对象间有数据依赖时,最好用此模式来对它
们进行解耦。

Mediator 模式让对象通过一个 Mediator 对象间接相互引用,从而对它们进行解耦。一个Mediator 对象为各 Colleague 对象间的请求提供路由,并集中它们的通信。因此,各 Colleague对象仅能通过 Mediator 接口相互通信。Mediator 接口是固定的,为了增加灵活性,Mediator 可能不得不实现它自己的分发策略。可以用一定方式对请求编码并打包参数,使得Colleague 对象可以请求的操作数目不限。由于此模式将通信行为集中到一个类中而不是将其分布在各个子类中,所以它可以减少一个系统的子类生成。

Chain of Responsibility 模式通过沿一个潜在接收者链传递请求而将发送者与接收者解耦。
因为发送者和接收者之间的接口是固定的,责任链可能也需要一个定制的分发策略。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/58289.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数字信号处理Python示例(6)使用指数衰减函数建模放射性衰变过程

文章目录 前言一、放射性衰变方程二、放射性衰变过程的Python仿真三、仿真结果分析写在后面的话 前言 使用指数衰减函数对放射性衰变进行了建模仿真,给出完整的Python仿真代码,并对仿真结果进行了分析。 一、放射性衰变方程 放射性衰变是一种自然现象&…

大数据新视界 -- 大数据大厂之 Impala 与内存管理:如何避免资源瓶颈(上)(5/30)

💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

AntFlow一款开源免费且自主可控的仿钉钉工作流引擎

在现代企业管理中,流程审批的高效性直接影响到工作的流畅度与生产力。最近,我发现了一个非常有趣的项目——AntFlow。这个项目不仅提供了一个灵活且可定制的工作流平台,还能让用户以可视化的方式创建和管理审批流程。 如果你寻找一个快速集成…

理解 WordPress | 第二篇:结构化分析

WordPress 专题致力于从 0 到 1 搞懂、用熟这种可视化建站工具。 第一阶段主要是理解。 第二阶段开始实践个人博客、企业官网、独立站的建设。 如果感兴趣,点个关注吧,防止迷路。 WordPress 的内容和功能结构可以按照层级来划分,这种层次化的…

省级-社会保障水平数据(2007-2022年)

社会保障水平是一个综合性的概念,它不仅涉及到一个国家或地区的社会保障制度覆盖范围,还包括了提供的保障种类与水平,以及这些制度在满足公民基本生活需求方面的能力。 2007-2022年省级-社会保障水平数据.zip资源-CSDN文库https://download.…

【毫米波雷达(三)】汽车控制器启动流程——BootLoader

汽车控制器启动流程——BootLoader 一、什么是Bootloader(BT)?二、FBL、PBL、SBL、ESS的区别三、MCU的 A/B分区的实现 一、什么是Bootloader(BT)? BT就是一段程序,一段引导程序。它包含了启动代码、中断、主程序等。 雷达启动需要由BT跳转到…

计算机网络——网络层导论

转发是局部功能——数据平面 路由是全局的功能——控制平面 网卡 网卡,也称为网络适配器,是计算机硬件中的一种设备,主要负责在计算机和网络之间进行数据传输。 一、主要功能 1、数据传输: 发送数据时,网卡将计算机…

使用 Python 调用云 API 实现批量共享自定义镜像

本文介绍如何通过 Python SDK 调用 API 接口,通过子用户批量共享云服务器自定义镜像。若您具备类似需求,或想了解如何使用 SDK,可参考本文进行操作。 前提条件 已创建子用户,并已具备云服务器及云 API 所有权限。 创建子用户请…

[mysql]修改表和课后练习

目录 DDL数据定义语言 添加一个字段 添加一个字段到最后一个 添加到表中的第一个一个字段 选择其中一个位置: 修改一个字段:数据类型,长度,默认值(略) 重命名一个字段 删除一个字段 重命名表 删除表 清空表 DCL中事务相关内容 DCL中COMMIT和ROLLBACK的讲解 对比TR…

Python异常检测 - LSTM(长短期记忆网络)

系列文章目录 Python异常检测- Isolation Forest(孤立森林) python异常检测 - 随机离群选择Stochastic Outlier Selection (SOS) python异常检测-局部异常因子(LOF)算法 Python异常检测- DBSCAN Python异常检测- 单类支持向量机(…

常见Transformer位置编码

文章目录 概述绝对位置编码相对位置编码T5 BiasALiBiRoPE 参考资料 概述 相对于RNN这样的序列模型来说,Transformer可并行是一个很大的优势,但可并行性带来一个问题,由于不是从前到后,所以模型对于位置信息是不敏感的。于是在Tra…

【IEEE出版 | EI稳定检索】2024智能机器人与自动控制国际学术会议 (IRAC 2024,11月29-12月1日)

2024智能机器人与自动控制国际学术会议 (IRAC 2024) 2024 International Conference on Intelligent Robotics and Automatic Control 官方信息 会议官网:www.icirac.org 2024 International Conference on Intelligent Robotics and Autom…

Golang | Leetcode Golang题解之第535题TinyURL的加密与解密

题目: 题解: import "math/rand"type Codec map[int]stringfunc Constructor() Codec {return Codec{} }func (c Codec) encode(longUrl string) string {for {key : rand.Int()if c[key] "" {c[key] longUrlreturn "http:/…

影响神经网络速度的因素- FLOPs、MAC、并行度以及计算平台

影响神经网络速度的四个主要因素分别是 FLOPs(浮点操作数)、MAC(内存访问成本)、并行度以及计算平台。这些因素共同作用,直接影响到神经网络的计算速度和资源需求。 1. FLOPs(Floating Point Operations&a…

【北京迅为】《STM32MP157开发板嵌入式开发指南》-第七十六章 C++入门

iTOP-STM32MP157开发板采用ST推出的双核cortex-A7单核cortex-M4异构处理器,既可用Linux、又可以用于STM32单片机开发。开发板采用核心板底板结构,主频650M、1G内存、8G存储,核心板采用工业级板对板连接器,高可靠,牢固耐…

小菜家教平台:基于SpringBoot+Vue打造一站式学习管理系统

前言 现在已经学习了很多与Java相关的知识,但是迟迟没有进行一个完整的实践(之前这个项目开发到一半,很多东西没学搁置了,同时原先的项目中也有很多的问题),所以现在准备从零开始做一个基于SpringBootVue的…

基于Matlab的语音识别

一、引言 语音识别技术是让计算机识别一些语音信号,并把语音信号转换成相应的文本或者命令的一种高科技技术。语音识别技术所涉及的领域非常广泛,包括信号处理、模式识别、人工智能等技术。近年来已经从实验室开始走向市场,渗透到家电、通信…

如何在 IntelliJ IDEA 中调整 `Ctrl+/` 快捷键生成注释的位置

前言 在使用 IntelliJ IDEA 编写代码时,注释是代码可读性和维护性的重要组成部分。IDEA 提供了快捷键 Ctrl/ 用于快速生成单行注释。然而,默认情况下,使用此快捷键生成的注释会出现在行首,导致注释与代码之间存在较大的空格&…

源鲁杯 2024 web(部分)

[Round 1] Disal F12查看: f1ag_is_here.php 又F12可以发现图片提到了robots 访问robots.txt 得到flag.php<?php show_source(__FILE__); include("flag_is_so_beautiful.php"); $a$_POST[a]; $keypreg_match(/[a-zA-Z]{6}/,$a); $b$_REQUEST[b];if($a>99999…

使用 ADB 在某个特定时间点点击 Android 设备上的某个按钮

前提条件 安装 ADB&#xff1a;确保你已经在计算机上安装了 Android SDK&#xff08;或单独的 ADB&#xff09;。并将其添加到系统环境变量中&#xff0c;以便你可以在命令行中运行 adb。 USB调试&#xff1a;确保 Android 设备已启用 USB 调试模式。这可以在设备的“设置” -…