架构模式
架构模式通常被记录为软件设计模式。架构模式通常使用相同的描述,作为给定上下文中软件架构中常见问题的通用、可重用解决方案。
什么是架构和什么是设计的分离并没有得到普遍的认同,也没有以任何公认的形式对模式进行编目。
软件架构是一个模糊的术语,它不仅涉及软件架构本身的学科,而且还涉及组件之间的结构和连接。
《软件体系结构导论》 这样描述它:“我们还远远没有一个被广泛接受的体系结构范例的分类,更不用说一个完全发展的软件体系结构理论了。但是我们现在可以清楚地识别出许多架构模式或风格,它们目前构成了软件架构师的基本技能。“
架构模式目录
- Multitier architecture 多层体系结构
- Model–view–controller 模型-视图-控制器
- Domain-driven design 领域驱动设计
- Blackboard pattern 黑板图案
- Sensor–controller–actuator 传感器-控制器-执行器
- Presentation–abstraction–control表示-抽象-控制
- Component-based 基于组件
- Monolithic application 单体应用
- Strangler fig pattern 勒颈无花果花纹
- Layered 层状
- Pipes and filters 管道和过滤器
- Database-centric 数据库中心
- Blackboard 黑板
- Rule-based 基于规则
- Event-driven aka implicit invocation 事件驱动又称隐式调用
- Publish-subscribe 发布订阅
- Asynchronous messaging 异步消息传递
- Microkernel 微内核
- Reflection 反射
- Client-server (multitier architecture exhibits this style) 客户端-服务器(多层架构展示了这种风格)
- Shared nothing architecture无共享体系结构
- Space-based architecture天基结构
- Object request broker 对象请求代理
- Peer-to-peer
- Representational state transfer (REST) 表述性状态转移(REST)
- Service-oriented 服务型
- Cloud computing patterns 云计算模式
架构模式是在给定的上下文中对软件架构中常见问题的通用的、可重用的解决方案。 架构模式解决了软件工程中的各种问题,例如计算机硬件性能限制、高可用性和最小化业务风险。一些架构模式已经在软件框架中实现。
在软件行业中使用“模式”这个词受到了传统架构中表达的类似概念的影响,例如Christopher亚历山大的A Pattern Language(1977),它讨论了建立模式词典的实践,促使计算机科学的从业者考虑他们自己的设计词典。
在Erich Gamma、Richard Helm、Ralph约翰逊和John Vlissides(现在通常被称为“四人帮”)出版了《设计模式》(1994)之后,这个比喻在软件工程专业中的使用变得司空见惯,这与公共互联网的早期发展相吻合,标志着复杂软件系统“吞噬世界”的开始,以及相应的需要在尽可能深的层次上对快速蔓延的软件开发世界进行编码,同时保持灵活性和适应性。
Architectural patterns are similar to software design patterns but have a broader scope.
架构模式类似于软件设计模式,但范围更广。
定义
即使架构模式传达了系统的图像,它也不是架构。架构模式是解决和描述软件架构的一些基本内聚元素的概念。无数不同的体系结构可能实现相同的模式并共享相关特性。模式通常被定义为“严格描述和普遍可用”。第0章第1章
架构风格
遵循传统的建筑体系结构,软件体系结构风格是一种特定的构造方法,其特征在于使其显着的特征。
架构样式定义:以结构组织模式表示的系统族;组件和连接器的词汇表,以及它们如何组合的约束。
架构风格是架构设计决策的命名集合,这些决策(1)适用于给定的开发环境,(2)约束特定于该环境中的特定系统的架构设计决策,以及(3)在每个结果系统中引出有益的品质。
有些人认为架构模式和架构风格是一样的, 有些人认为风格是模式的特殊化。它们的共同点是模式和样式都是架构师使用的习惯用法,它们“提供了一种公共语言” 或“词汇表” 来描述系统类。
主要的区别是模式可以被看作是问题的解决方案,而样式则更一般,不需要解决问题来获得外观。
分析
软件是由它的问题空间来管理的,解决方案可以应用到问题空间中。下表显示了如何跨各种问题空间考虑软件,这些问题空间由子域定义,并使用相应的软件设计模式和解决方案模式进行处理。子域可以被合并到其他子域的分析中,例如,解决人工智能问题首先是作为数据架构问题来处理的。
更多信息子域区域,架构模式...
| Sub-domain area | Architecture pattern 架构模式 | Software design patterns软件设计模式 | Solution patterns 解决方案模式 | Related patterns 相关模式 |
| Data integration/SOA 数据集成/ SOA | • ETL (data extraction transformation and loading)ETL(数据提取、转换和加载) | • Change data capture 变更数据捕获 • Near real-time ETL 近实时ETL • Batch ETL 批量ETL • Data discovery 数据发现 | • Error handling 错误处理 • Job scheduling 作业调度 • Data validation 数据验证 • Slowly changing dimensions load缓慢变化的尺寸载荷 | • EAI • Master data hub 主数据中心 • Operational data store (ODS)业务数据存储 • Data mart 数据集市 • Data warehouse 数据仓库 |
| • MFT | ||||
| • EAI/ESB | • Publish/subscribe 发布/订阅 • Request/reply 请求/回复 • Message exchange patterns消息交换模式 | • One-way 单向 • Synchronous request/response同步请求/响应 • Basic callback 基本回调 • Claim check | • SOA | |
| Data architecture 数据架构 | • Transaction data stores (TDS/OLTP)事务数据存储(TDS/OLTP) • Master data store 主要数据存储 • Operational data store 运营数据存储 • Big data 大数据 • Data mart 数据集市 • Data warehouse 数据仓库 | • Custom applications databases自定义应用程序数据库 • Packaged application databases打包的应用程序数据库 | • Clustered File System 集群文件系统 • NoSQL Database NoSQL数据库 | • ETL • EAI • SOA • MapReduce |
| Analytics and business intelligence分析和商业智能 | • Transactional reporting 跨媒体报道 • Operational analytics • Business analytics 业务分析 • Predictive analytics 预测分析 • Prescriptive analytics 规范性分析 • Streaming analytics 流分析 • Data science and advanced analytics数据科学和高级分析 • NLP | • Transactional reporting data access事务报告数据访问 • Operational reporting data access操作报告数据访问 • Analytical reporting data access分析报告数据访问 • Analytical dashboard data access分析仪表板数据访问 • Operational dashboard data access操作仪表板数据访问 • Data mining 数据挖掘 | • Real-time dashboards 实时仪表板 • In-memory analytics 内存分析 • Statistical analysis 统计分析 • Predictive analytics 预测分析 | • ETL • EAI • TDS • Operational data store 运营数据存储 • Data mart 数据集市 |
| Master data management 主数据管理 | • Master data hub 主数据中心 | • Master data replication 主数据复制 • Master data services • Master data synchronization主数据同步 | • Change data capture 变更数据捕获 • EAI • STD[clarification needed] 标准品编号0# | |
| Data modeling 数据建模 | • Dimensional data modeling维度数据建模 • E-R data modeling E-R数据建模 | • Modeling standards 建模标准 • Naming conventions 命名约定 | ||
| Artificial intelligence 人工智能 | • Decision management 决策管理 • Speech recognition 语音识别 • Text analytics and NLP文本分析和NLP • Natural language generation自然语言生成 • Classic machine learning经典机器学习 • Deep learning 深度学习 • Robotic process automation机器人流程自动化 • Image and video analysis 图像和视频分析 |
示例
架构模式的一些示例:
- Blackboard system 黑板系统
- Broker pattern 中介模式
- Event-driven architecture事件驱动架构
- Implicit invocation 隐式调用
- Layers 层
- Hexagonal architecture 地函式建筑
- Microservices 微服务
- Action–domain–responder, 域应答器,
- Entity component system 实体组件系统
- Entity-control-boundary 权限控制边界
- Multitier architecture (often three-tier or n tier) 多层体系结构(通常为三层或n层)
- Object-oriented programming面向对象编程
- Naked objects 裸对象
- Operational data store (ODS) 业务数据存储
- Peer-to-peer
- Pipe and filter architecture管道和过滤器架构
- Service-oriented architecture面向服务的体系结构
- Space-based architecture天基结构
- Distributed hash table 分布式哈希表
- Publish–subscribe pattern发布-订阅模式
- Message broker 消息代理
- Hierarchical model–view–controller分层模型-视图-控制器
设计模式
在软件工程中,软件设计模式是一种通用的,可重用的解决方案,用于解决软件设计中给定上下文中经常出现的问题。它不是一个可以直接转换为源代码或机器代码的完成设计。相反,它是如何解决问题的描述或模板,可以在许多不同的情况下使用。设计模式是程序员在设计应用程序或系统时可以用来解决常见问题的形式化的最佳实践。
面向对象的设计模式通常显示类或对象之间的关系和交互,而不指定最终涉及的应用程序类或对象。隐含可变状态的模式可能不适合函数式编程语言。有些模式在具有解决它们试图解决的问题的内置支持的语言中可能是不必要的,并且面向对象模式不一定适合非面向对象语言。
设计模式可以被看作是一种结构化的计算机编程方法,介于编程范式和具体算法之间。
History 历史
早在1977年,克里斯托弗亚历山大(Christopher Alexander)就将模式作为一个建筑概念提出来。“The Pattern of Streets,”Journal OF THE AIP,September,1966,Vol.32,No.5,pp.273-278). 1987年,肯特贝克和沃德坎宁安开始尝试将模式应用于编程的想法-特别是模式语言-并在当年的OOPSLA会议上展示了他们的结果。在接下来的几年里,贝克,坎宁安和其他人继续这项工作。
在1994年所谓的“Gang of Four”(Gamma等人)出版了《设计模式:可重用面向对象软件的元素》一书之后,设计模式在计算机科学中变得流行起来,其通常缩写为“GoF”。同年,第一届编程会议的模式语言举行,次年,波特兰模式库成立,用于设计模式的文档编制。该词的范围仍有争议。设计模式类型的著名书籍包括:
- 约翰逊,Ralph; Vlissides,John.设计模式:可重用面向对象软件的元素。艾迪森-韦斯利ISBN 978-0-201-63361-0。
- Brinch汉森,佩尔(1995年)。计算科学研究:并行编程范例。普伦蒂斯厅。ISBN 978-0-13-439324-7。
- 面向模式的软件架构,第1卷:模式系统。约翰威利父子公司ISBN 978-0-471-95869-7。
- Beck,肯特(1997年)。Smalltalk最佳实践模式普伦蒂斯厅。ISBN 978-0134769042。
- 施密特,道格拉斯C.; Stal,Michael; Rohnert,Hans; Buschmann,Frank.面向模式的软件架构,第2卷:并发和网络对象的模式。约翰威利父子公司ISBN 978-0-471-60695-6。
- 企业应用程序架构模式。艾迪森-韦斯利ISBN 978-0-321-12742-6。
- 企业集成模式:设计、构建和部署消息传递解决方案。艾迪森-韦斯利ISBN 978-0-321-20068-6。
- Head First设计模式O'Reilly Media. ISBN 978-0-596-00712-6。
- Larman,克雷格.应用UML和模式(艾德第3版,艾德第1版,1995年)。皮尔森ISBN 978-0131489066。
虽然设计模式在实际中的应用已经有很长一段时间了,但设计模式概念的形式化却一直处于停滞状态。
结构
设计模式由几个部分组成(参见下面的文档)。特别感兴趣的是结构、参与者和协作部分。这些部分描述了一个设计主题:一个原型微架构,开发人员可以复制并适应他们的特定设计,以解决设计模式所描述的经常性问题。微架构是一组程序组成部分(例如,类,方法.)和他们的关系。开发人员通过在他们的设计中引入这种原型微架构来使用设计模式,这意味着他们设计中的微架构将具有与所选设计主题相似的结构和组织。
领域特定模式
人们还努力编纂特定领域的设计模式,包括使用现有的设计模式以及特定领域的设计模式。例子包括用户界面设计模式, 信息可视化, 安全设计, “安全可用性”, Web设计 和商业模式设计。
Pattern Languages of Programming
每年一度的编程语言会议论文集 包含了许多特定领域模式的例子。
分类和列表
设计模式最初根据它们解决的问题类型分为3个子分类。创建模式提供了基于所需标准以受控方式创建对象的能力。结构模式是关于组织不同的类和对象以形成更大的结构并提供新的功能。最后,行为模式是关于识别对象之间的公共通信模式并实现这些模式。
23 classic software design patterns
Creational:Creational patterns 是创建对象的模式,而不是必须直接实例化对象。这使程序在决定需要为给定情况创建哪些对象时具有更大的灵活性。
- Abstract factory:抽象工厂组对象工厂有一个共同的主题。
- Builder :Builder通过分离构造和表示来构造复杂对象。
- Factory method :工厂方法创建对象而不指定要创建的确切类。
- Prototype :Prototype通过克隆现有对象来创建对象。
- Singleton :Singleton将一个类的对象创建限制为只有一个实例。
Structural:Structural patterns 关注类和对象的组合。它们使用继承来组合接口,并定义组合对象以获得新功能的方法。
- Adapter :适配器允许具有不兼容接口的类一起工作,方法是将自己的接口包装在已经存在的类的接口周围。
- Bridge :Bridge从它的实现中抽象出来,这样两者就可以独立变化。
- Composite :复合将零个或多个类似对象组合在一起,以便可以将它们作为一个对象进行操作。
- Decorator :装饰器动态地添加/覆盖对象的现有方法中的行为。
- Facade :Facade为大量代码提供了一个简化的接口。
- Flyweight :Flyweight降低了创建和操作大量类似对象的成本。
- Proxy :代理为另一个对象提供占位符,以控制访问、降低成本和复杂性。
Behavioral:大多数 behavioral design patterns 都特别关注对象之间的通信。
- Chain of responsibility :责任链将命令委托给处理对象链。
- Command :命令创建封装操作和参数的对象。
- Interpreter :解释器实现一种专用语言。
- Iterator :迭代器顺序访问对象的元素,而不公开其底层表示。
- Mediator :Mediator允许类之间的松散耦合,因为它是唯一一个详细了解其方法的类。
- Memento :Memento提供了将对象恢复到其先前状态(撤消)的能力。
- Observer :Observer是一种发布/订阅模式,它允许多个observer对象看到一个事件。
- State :状态允许对象在其内部状态改变时改变其行为。
- Strategy :策略允许在运行时即时选择算法家族中的一个。
- Template method :模板方法将算法的框架定义为一个抽象类,允许它的子类提供具体的行为。
- Visitor :Visitor通过将方法的层次结构移动到一个对象中,将算法从对象结构中分离出来。
Creational patterns
| Name 名称 | Description 描述 | In Design Patterns 在设计模式 | In Code Complete 在代码中完成 | Other 其他 |
| Abstract factory 抽象工厂 | 提供一个接口,用于创建相关或依赖对象的族,而无需指定它们的具体类。 | Yes | Yes | — |
| Builder | 将复杂对象的构造与其表示分离,允许相同的构造过程创建各种表示。 | Yes | Yes | — |
| Dependency Injection 依赖注入 | 类从注入器接受它需要的对象,而不是直接创建对象。 | — | Yes | — |
| Factory method 工厂方法 | 定义一个用于创建单个对象的接口,但让子类决定实例化哪个类。工厂方法允许类将实例化推迟到子类。 | Yes | Yes | — |
| Lazy initialization 延迟初始化 | 延迟创建对象、计算值或其他昂贵过程的策略,直到第一次需要它。此模式在GoF目录中作为“虚拟代理”出现,这是代理模式的一种实现策略。 | Yes | Yes | PoEAA |
| Multiton 多例 | 确保类只有命名实例,并提供对它们的全局访问点。 | Yes | Yes | Yes |
| Object pool 对象池 | 通过回收不再使用的对象来避免昂贵的资源获取和释放。可以认为是连接池和线程池模式的概括。 | Yes | Yes | Yes |
| Prototype 原型 | 使用原型实例指定要创建的对象类型,并从现有对象的“骨架”创建新对象,从而提高性能并将内存占用保持在最低限度。 | Yes | Yes | Yes |
| Resource acquisition is initialization (RAII)资源获取即初始化 | 通过将资源与合适对象的生命周期绑定,确保资源得到适当释放。 | Yes | Yes | Yes |
| Singleton | 确保一个类只有一个实例,并提供一个全局访问点。 | Yes | Yes | Yes |
Structural patterns
| Name 名称 | Description 描述 | In Design Patterns 在设计模式 | In Code Complete 在代码中完成 | Other 其他 |
| Adapter, Wrapper, or Translator适配器、包装器或转换器 | 将一个类的接口转换成客户端期望的另一个接口。适配器允许类一起工作,否则由于接口不兼容而不能一起工作。企业集成模式的等价物是翻译器。 | Yes | Yes | Yes |
| Bridge 桥 | 将抽象与其实现解耦,允许两者独立变化。 | Yes | Yes | Yes |
| Composite 复合 | 将对象组合到树结构中以表示部分-整体层次结构。Composite允许客户端统一处理单个对象和对象的组合。 | Yes | Yes | Yes |
| Decorator 装饰器 | 动态地将额外的责任附加到对象上,保持相同的接口。装饰器为扩展功能提供了一种灵活的子类化方法。 | Yes | Yes | Yes |
| Delegation 代表团 | 通过组合而不是子类来扩展类。对象通过委托给第二个对象(委托)来处理请求 | Yes | Yes | Yes |
| Extension object 扩展对象 | 在不更改层次结构的情况下向层次结构添加功能。 | Yes | Yes | Yes |
| Facade 立面 | 为子系统中的一组接口提供统一的接口。Facade定义了一个更高级别的接口,使子系统更易于使用。 | Yes | Yes | Yes |
| Flyweight | 使用共享来有效地支持大量类似对象。 | Yes | Yes | Yes |
| Front controller 前端控制器 | 该模式与Web应用程序的设计有关。它为处理请求提供了一个集中的入口点。 | Yes | Yes | J2EE Patterns PoEAAJ2EE模式 PoEAA |
| Marker 标记 | 将元数据与类关联的空接口。 | Yes | Yes | Effective Java 有效的Java |
| Module 模块 | 将多个相关元素(如类、单例、方法、全局使用)组合到一个概念实体中。 | Yes | Yes | Yes |
| Proxy 代理 | 为另一个对象提供代理项或占位符以控制对它的访问。 | Yes | Yes | Yes |
| Twin 双床房 | Twin允许在不支持多重继承特性的编程语言中对多重继承进行建模。 | Yes | Yes | Yes |
Behavioral patterns
| Name 名称 | Description 描述 | In Design Patterns 在设计模式 | In Code Complete 在代码中完成 | Other 其他 |
| Blackboard 黑板 | 用于组合不同数据源的人工智能模式(参见黑板系统) | Yes | Yes | Yes |
| Chain of responsibility 责任链 | 通过给多个对象处理请求的机会,避免将请求的发送方耦合到其接收方。将接收对象链接起来,并沿着链沿着传递请求,直到有一个对象处理它。 | Yes | Yes | Yes |
| Command 命令 | 将请求封装为对象,从而允许对具有不同请求的客户端进行参数化,以及对请求进行排队或记录。它还允许支持无法撤消的操作。 | Yes | Yes | Yes |
| Fluent interface 连贯接口 | 将API设计为方法链,使其读起来像DSL。每个方法调用都返回一个上下文,通过该上下文可以进行下一个逻辑方法调用。 | Yes | Yes | Yes |
| Interpreter 解释器 | 给定一种语言,定义其语法的表示沿着解释器,解释器使用该表示来解释该语言中的句子。 | Yes | Yes | Yes |
| Iterator 迭代器 | 提供一种顺序访问聚合对象的元素而不公开其底层表示的方法。 | Yes | Yes | Yes |
| Mediator 调解人 | 定义一个封装一组对象如何交互的对象。Mediator通过避免对象显式地相互引用来促进松耦合,并允许它们的交互独立地变化。 | Yes | Yes | Yes |
| Memento 纪念品 | 在不违反封装的情况下,捕获并外部化对象的内部状态,允许对象稍后恢复到该状态。 | Yes | Yes | Yes |
| Null object Null对象 | 通过提供默认对象来避免空引用。 | Yes | Yes | Yes |
| Observer or Publish/subscribe观察员或发布/订阅 | 定义对象之间的一对多依赖关系,其中一个对象中的状态更改会导致其所有依赖项被通知并自动更新。 | Yes | Yes | Yes |
| Servant 仆人 | 为一组类定义公共功能。Servant模式也经常被称为helper类或一组给定类的实用程序类实现。助手类通常没有对象,因此它们都有作用于不同类型的类对象的静态方法。 | Yes | Yes | Yes |
| Specification 规范 | 以布尔方式表示的业务逻辑。 | Yes | Yes | Yes |
| State 状态 | 允许对象在其内部状态改变时改变其行为。对象将显示为更改了其类。 | Yes | Yes | Yes |
| Strategy 战略 | 定义一系列算法,封装每个算法,并使它们可以互换。策略允许算法独立于使用它的客户端而变化。 | Yes | Yes | Yes |
| Template method 模板法 | 在操作中定义算法的框架,将一些步骤推迟到子类。模板方法允许子类重新定义算法的某些步骤,而不改变算法的结构。 | Yes | Yes | Yes |
| Visitor 访客 | 表示要在一组类的实例上执行的操作。Visitor允许定义新的操作,而不改变它所操作的元素的类。 | Yes | Yes | Yes |
Concurrency patterns并发模式
| Name 名称 | Description 描述 | In POSA2 在POSA2 中 | Other 其他 |
| Active Object 活动对象 | 将方法执行与驻留在它们自己的控制线程中的方法调用解耦。目标是通过使用异步方法调用和调度器来处理请求,从而引入并发性。 | Yes | — |
| Balking 止步 | 仅当对象处于特定状态时才对对象执行操作。 | No | — |
| Binding properties 结合特性 | 结合多个观察者来强制不同对象中的属性以某种方式同步或协调。 | No | — |
| Compute kernel 计算内核 | 相同的计算可以并行进行多次,不同的是整数参数与非分支指针数学一起用于共享数组,例如GPU优化的矩阵乘法或卷积神经网络。 | No | — |
| Double-checked locking 双重检查锁定 | 通过首先以不安全的方式测试锁定标准(“锁定提示”)来减少获取锁的开销;只有当测试成功时,实际的锁定逻辑才继续进行。 在某些语言/硬件组合中实现时可能不安全。因此,有时可以将其视为反模式。 | Yes | — |
| Event-based asynchronous基于事件的异步 | 解决多线程程序中出现的异步模式问题。 | No | — |
| Guarded suspension 防护悬挂 | 管理需要在执行操作之前获取锁并满足前提条件的操作。 | No | — |
| Join 加入 | 联接模式提供了一种通过消息传递来编写并发、并行和分布式程序的方法。与线程和锁的使用相比,这是一种高级编程模型。 | No | — |
| Lock 锁 | 一个线程在资源上放置一个“锁”,防止其他线程访问或修改它。 | No | PoEAA |
| Messaging design pattern (MDP)消息传递设计模式 | 允许在组件和应用程序之间交换信息(即消息)。 | No | — |
| Monitor object 监视器对象 | 一种对象,其方法受到互斥的影响,从而防止多个对象错误地试图同时使用它。 | Yes | — |
| Reactor 反应器 | 反应器对象为必须同步处理的资源提供异步接口。 | Yes | — |
| Read-write lock 读写锁 | 允许对对象进行并发读访问,但要求对写操作进行独占访问。底层的信号量可以用于写入,并且可以使用或不使用写时复制机制。 | No | — |
| Scheduler 调度器 | 当线程可以执行单线程代码时,解释控件。 | No | — |
| Service handler pattern 服务处理程序模式 | 对于每个请求,服务器生成一个专用的客户端处理程序来处理请求。 也称为thread-per-session。 | No | — |
| Thread pool 线程池 | 创建多个线程来执行多个任务,这些任务通常组织在队列中。通常,任务比线程多得多。可以认为是对象池模式的一个特例。 | No | — |
| Thread-specific storage 线程专用存储器 | 线程本地的静态或“全局”内存。 | Yes | — |
| Safe Concurrency with Exclusive Ownership具有独占所有权的安全并发 | 避免了对运行时并发机制的需要,因为可以证明独占所有权。这是Rust语言的一个值得注意的功能,但编译时检查并不是唯一的方法,程序员通常会手动将这些模式设计到代码中-省略锁定机制的使用,因为程序员评估给定的变量永远不会被并发访问。 | No | — |
| CPU atomic operation CPU原子操作 | x86和其他CPU体系结构支持一系列原子指令,这些指令保证了修改和访问原始值(整数)的内存安全性。例如,两个线程都可以安全地递增计数器。这些功能也可以用于实现上述其他并发模式的机制。C#语言使用Interlocked类来实现这些功能。 | No | — |
Documentation 文件
设计模式的文档描述了使用该模式的上下文、该模式试图解决的上下文中的力以及建议的解决方案。 没有单一的标准格式来记录设计模式。相反,不同的模式作者使用了各种不同的格式。然而,根据Martin Fowler的说法,某些模式形式已经变得比其他形式更知名,因此成为新模式写作工作的共同起点。 一个常用的文档格式的例子是Erich Gamma、Richard Helm、Ralph约翰逊和John Vlissides在他们的书《设计模式》中使用的格式。它包含以下部分:
- 模式名称和分类:一个描述性的唯一名称,有助于识别和引用模式。
- 意图:对模式背后的目标和使用它的原因的描述。
- 也称为:模式的其他名称。
- 动机(Forces):由问题和上下文组成的场景,可以在其中使用此模式。
- 适用性:该模式可用的情况;该模式的上下文。
- 结构:图案的图形表示。类图和交互图可用于此目的。
- Participants:模式中使用的类和对象的列表,以及它们在设计中的角色。
- 协作:描述模式中使用的类和对象如何相互交互。
- 后果:对使用模式所导致的结果、副作用和权衡的描述。
- 实现:对模式实现的描述;模式的解决方案部分。
- 示例代码:说明如何在编程语言中使用模式。
- 已知用法:模式的真实的用法示例。
- 相关模式:与该模式有某种关系的其他模式;讨论该模式与类似模式之间的差异。
Criticism 批评
已经观察到,设计模式可能只是给定编程语言(例如Java或C++)中缺少某些功能的标志。Peter Norvig演示了《设计模式》一书中的23种模式中的16种(主要集中在C++上)在Lisp或Dylan中被简化或删除(通过直接语言支持)。Hannemann和Kiczales使用面向方面的编程语言(AASPJ)实现了23种设计模式中的几种,并表明从23种设计模式中的17种实现中删除了代码级依赖关系,并且面向方面的编程可以简化设计模式的实现。保罗·格雷厄姆(Paul Graham)的文章《书呆子的复仇》(Revenge of the Nerds)。
不适当地使用模式可能会不必要地增加复杂性。
C++中的设计模式
C++是一种强大的编程语言,支持多种编程设计模式。以下是一些常见的C++编程设计模式:
- 工厂模式(Factory Pattern):工厂模式是一种创建型模式,它提供了一种创建对象的最佳方式,而无需暴露对象的创建逻辑。在工厂模式中,我们使用一个工厂类来创建对象,而不是在客户端代码中直接实例化对象。
- 单例模式(Singleton Pattern):单例模式是一种创建型模式,它确保一个类只有一个实例,并提供一个全局访问点来访问该实例。在C++中,我们可以使用静态成员变量和静态成员函数来实现单例模式。
- 观察者模式(Observer Pattern):观察者模式是一种行为型模式,它定义了对象之间的一对多依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都会自动收到通知并更新。
- 策略模式(Strategy Pattern):策略模式是一种行为型模式,它定义了一系列算法,将每个算法都封装起来,并使它们可以互换。在C++中,我们可以使用函数指针或函数对象来实现策略模式。
- 装饰器模式(Decorator Pattern):装饰器模式是一种结构型模式,它允许在不更改对象接口的情况下动态地添加行为。在C++中,我们可以使用继承来实现装饰器模式。
- 适配器模式(Adapter Pattern):适配器模式是一种结构型模式,它允许将不兼容的对象包装在适配器中,以便它们可以一起工作。在C++中,我们可以使用类适配器或对象适配器来实现适配器模式。
- 桥接模式(Bridge Pattern):桥接模式是一种结构型模式,它将抽象和实现分离,以便它们可以独立地变化。在C++中,我们可以使用虚函数或函数指针来实现桥接模式。
- 原型模式(Prototype Pattern):原型模式是一种创建型模式,它允许我们通过复制现有对象来创建新对象。在C++中,我们可以使用拷贝构造函数或赋值运算符来实现原型模式。
- 组合模式(Composite Pattern):组合模式是一种结构型模式,它允许我们将对象组合成树形结构,以表示“部分-整体”的层次结构。在C++中,我们可以使用递归组合来实现组合模式。
- 迭代器模式(Iterator Pattern):迭代器模式是一种行为型模式,它提供了一种顺序访问聚合对象元素的方法,而无需暴露聚合对象的内部表示。在C++中,我们可以使用STL中的迭代器来实现迭代器模式。
- 访问者模式(Visitor Pattern):访问者模式是一种行为型模式,它允许我们在不更改对象结构的情况下定义新的操作。在C++中,我们可以使用双重分派技术来实现访问者模式。
- 建造者模式(Builder Pattern):建造者模式是一种创建型模式,它允许我们逐步构建复杂对象,而无需暴露对象的创建过程。在C++中,我们可以使用链式调用或者在类中定义一个Builder类来实现建造者模式。
- 备忘录模式(Memento Pattern):备忘录模式是一种行为型模式,它允许我们在不破坏封装性的前提下,捕获并存储一个对象的内部状态,并在需要时将其恢复。在C++中,我们可以使用拷贝构造函数或者序列化/反序列化来实现备忘录模式。
- 解释器模式(Interpreter Pattern):解释器模式是一种行为型模式,它定义了一种语言和解释器,用于解释该语言中的表达式。在C++中,我们可以使用递归下降解析器或者使用ANTLR等工具来实现解释器模式。
- 职责链模式(Chain of Responsibility Pattern):职责链模式是一种行为型模式,它允许我们将请求沿着处理链传递,直到有一个处理者能够处理该请求为止。在C++中,我们可以使用虚函数或者函数指针来实现职责链模式。
- 中介者模式(Mediator Pattern):中介者模式是一种行为型模式,它允许我们将多个对象之间的交互行为集中到一个中介者对象中,以减少对象之间的耦合度。在C++中,我们可以使用回调函数或者使用观察者模式来实现中介者模式。
- 外观模式(Facade Pattern):外观模式是一种结构型模式,它为复杂子系统提供了一个简单的接口,以便客户端可以更方便地使用该子系统。在C++中,我们可以使用类或者命名空间来实现外观模式。
- 模板方法模式(Template Method Pattern):模板方法模式是一种行为型模式,它定义了一个算法的骨架,而将一些步骤的实现留给子类来完成。在C++中,我们可以使用虚函数或者函数指针来实现模板方法模式。
- 状态模式(State Pattern):状态模式是一种行为型模式,它允许对象在内部状态发生改变时改变它的行为。在C++中,我们可以使用虚函数或者函数指针来实现状态模式。
- 命令模式(Command Pattern):命令模式是一种行为型模式,它将请求封装成对象,以便我们可以将请求的参数化、队列化或记录日志。在C++中,我们可以使用函数指针或者函数对象来实现命令模式。
- 过滤器模式(Filter Pattern):过滤器模式是一种结构型模式,它允许我们使用不同的标准来过滤一组对象。在C++中,我们可以使用函数对象或者函数指针来实现过滤器模式。
- 细胞自动机模式(Cellular Automaton Pattern):细胞自动机模式是一种计算模型,它由一个网格中的单元格组成,每个单元格可以处于一组离散的状态中。在C++中,我们可以使用多维数组或者STL中的容器来实现细胞自动机模式。
- 享元模式(Flyweight Pattern):享元模式是一种结构型模式,它允许我们共享对象以减少内存使用。在C++中,我们可以使用对象池或者使用STL中的容器来实现享元模式。
- 代理模式(Proxy Pattern):代理模式是一种结构型模式,它允许我们使用一个代理对象来控制对另一个对象的访问。在C++中,我们可以使用类或者函数对象来实现代理模式。
- 模板模式(Template Pattern):模板模式是一种行为型模式,它将算法的骨架定义在一个抽象基类中,而将一些步骤的实现留给子类来完成。在C++中,我们可以使用虚函数或者函数指针来实现模板模式。
- 模型-视图-控制器模式(Model-View-Controller Pattern):模型-视图-控制器模式是一种架构模式,它将应用程序分为三个部分:模型、视图和控制器。在C++中,我们可以使用类或者函数对象来实现模型-视图-控制器模式。
设计模式实现
1. 关联(Association)
关联是一种强关系,表示一个类对象可以长期拥有另一个类的对象,通常以成员变量的形式出现。关联关系表明两个类之间存在一种稳定且持久的联系。例如,一个公司和它的员工、一个大学和它的学生之间的关系都是关联关系。
特点
- 关联关系是一种强关系,一个类持续拥有另一个类的对象。
- 关联可以是单向或双向的,也可以是多对多的。
- 在代码上,关联关系通常通过成员变量表示。
代码示例
以一个公司拥有多个员工为例:
class Employee {
public:
std::string name;
Employee(const std::string& name) : name(name) {}
};
class Company {
private:
std::vector<Employee> employees; // 关联:Company 拥有 Employee 对象
public:
void addEmployee(const Employee& employee) {
employees.push_back(employee);
}
}; 在这个例子中,Company 和 Employee 之间是一个单向的关联关系。Company 拥有 Employee 的对象(成员变量 employees),但 Employee 并不需要知道 Company 的存在。这是一种持久的关系,Company 的生命周期包含了 Employee 的生命周期。
2. 依赖(Dependency)
依赖是一种弱关系,表示一个类在某种情况下会临时使用另一个类。依赖关系表明一个类的方法参数或返回值中包含另一个类的对象,通常是短暂且临时的联系。例如,一个打印机类依赖于打印文档类,但打印机在打印结束后不需要持续拥有该文档。
特点
- 依赖关系是一种弱关系,一个类的对象只在需要时才使用另一个类。
- 依赖通常是短暂的、临时的,例如在函数参数中。
- 在代码上,依赖关系通常通过方法参数、返回值或局部变量表示。
代码示例
以打印机依赖于打印文档为例:
class Document {
public:
std::string content;
Document(const std::string& content) : content(content) {}
};
class Printer {
public:
void printDocument(const Document& doc) { // 依赖:Printer 使用 Document 对象
std::cout << "Printing: " << doc.content << std::endl;
}
}; 在这个例子中,Printer 类的 printDocument 方法依赖于 Document 类,但 Printer 并不拥有 Document 对象。Document 只是作为参数传递给 printDocument 方法,一旦该方法执行完成,Printer 对 Document 的依赖关系就结束了。
3. 聚合(Aggregation)
聚合是一种弱类型的“整体-部分”关系,表示一个对象包含另一个对象,但被包含的对象(部分)可以独立存在。聚合关系通常描述一种**“拥有”**的关系,但整体对象的生命周期并不会控制部分对象的生命周期。
特点
- 弱生命周期:部分对象的生命周期独立于整体对象。即便整体对象被销毁,部分对象也可以存在。
- 代码表现:聚合关系通常通过指针或引用来表示,表示该部分对象是外部创建并传递给整体对象的。
- 逻辑关系:整体对象只是对部分对象的引用,部分对象可以被多个整体对象共享。
代码示例
以“学校包含多个教师”为例,教师可以独立存在于学校之外。
cpp
Copy code
class Teacher {
public:
std::string name;
Teacher(const std::string& name) : name(name) {}
};
class School {
private:
std::vector<Teacher*> teachers; // 聚合关系:School 拥有 Teacher 指针,但不负责其生命周期
public:
void addTeacher(Teacher* teacher) {
teachers.push_back(teacher);
}
};
在这个例子中:
-
School和Teacher之间是一个聚合关系。School通过指针引用教师对象,但并不负责教师对象的创建和销毁。 -
Teacher对象可以在多个School对象中共享,也可以独立存在,不依赖于任何一个School的生命周期。
4. 组合(Composition)
组合是一种强类型的“整体-部分”关系,表示一个对象严格包含另一个对象,被包含的对象(部分)依赖于整体对象的生命周期。组合关系通常描述一种**“包含”**的关系,部分对象不能脱离整体对象而独立存在。
特点
- 强生命周期:部分对象的生命周期由整体对象控制。当整体对象销毁时,部分对象也会被销毁。
- 代码表现:组合关系通常通过值类型或智能指针来表示,由整体对象负责部分对象的创建和销毁。
- 逻辑关系:部分对象严格依赖整体对象的存在,无法被其他对象共享。
代码示例
以“人和他们的心脏”为例,心脏对象依赖于人的生命周期,不能脱离人而单独存在。
class Heart {
public:
void beat() {
std::cout << "Heart is beating..." << std::endl;
}
};
class Person {
private:
Heart heart; // 组合关系:Person 包含 Heart,并负责其生命周期
public:
void live() {
heart.beat();
}
}; 在这个例子中:
-
Person和Heart之间是一个组合关系。Person对象销毁时,Heart对象也会销毁。 -
Heart对象无法脱离Person而独立存在。
| 特性 | 关联(Association) | 依赖(Dependency) | 组合(Composition) | 聚合(Aggregation) |
| 定义 | 两个类之间存在联系,但生命周期独立 | 临时性的使用关系,不持有对方引用 | 强“整体-部分”关系,部分依赖整体的生命周期 | 弱“整体-部分”关系,部分可以独立存在 |
| 关系强度 | 弱耦合(0..多) | 非常弱的临时耦合 | 强耦合(1..多) | 中等耦合(0..多) |
| 生命周期管理 | 各自独立 | 短暂使用 | 由整体管理,整体销毁则部分销毁 | 各自独立 |
| 代码表现 | 指针或引用作为成员变量 | 方法参数、局部变量或返回值 | 值类型或智能指针作为成员变量 | 指针或引用作为成员变量 |
| 示例 | 学校和教师 | 打印机依赖文档 | 人和心脏 | 班级和学生 |
创建型模式
Factory
Factory 模式的两个最重要的功能:
- 定义创建对象的接口,封装了对象的创建;
- 使得具体化类的工作延迟到了子类中。
示例代码:
#include <iostream>
// 抽象产品类
class Product {
public:
virtual void Operation() const = 0;
virtual ~Product() {}
};
// 具体产品类1
class ConcreteProduct1 : public Product {
public:
void Operation() const override {
std::cout << "Operation of ConcreteProduct1" << std::endl;
}
};
// 具体产品类3(似乎是应该有ConcreteProduct2,这里直接跳到ConcreteProduct3)
class ConcreteProduct3 : public Product {
public:
void Operation() const override {
std::cout << "Operation of ConcreteProduct3" << std::endl;
}
};
// 抽象工厂类
class Factory {
public:
virtual Product* CreateProduct() const = 0;
virtual ~Factory() {}
};
// 具体工厂类
class ConcreteFactory : public Factory {
public:
Product* CreateProduct() const override {
// 根据需要创建不同的产品实例
return new ConcreteProduct1(); // 或者根据某些条件返回 ConcreteProduct3
}
};
int main() {
// 创建具体工厂对象
const Factory* factory = new ConcreteFactory();
// 使用工厂创建产品对象
const Product* product = factory->CreateProduct();
product->Operation();
// 释放资源
delete product;
delete factory;
return 0;
} AbstactFactory
AbstactFactory 模式用来创建一组相关或者相互依赖的对象
示例代码:
#include <iostream>
// 抽象产品A的接口
class AbstractProductA {
public:
virtual void Operation() const = 0;
virtual ~AbstractProductA() {}
};
// 抽象产品B的接口
class AbstractProductB {
public:
virtual void Operation() const = 0;
virtual ~AbstractProductB() {}
};
// 具体产品A1
class ProductA1 : public AbstractProductA {
public:
void Operation() const override {
std::cout << "Operation of ProductA1" << std::endl;
}
};
// 具体产品A2
class ProductA2 : public AbstractProductA {
public:
void Operation() const override {
std::cout << "Operation of ProductA2" << std::endl;
}
};
// 具体产品B1
class ProductB1 : public AbstractProductB {
public:
void Operation() const override {
std::cout << "Operation of ProductB1" << std::endl;
}
};
// 具体产品B2
class ProductB2 : public AbstractProductB {
public:
void Operation() const override {
std::cout << "Operation of ProductB2" << std::endl;
}
};
// 抽象工厂接口
class AbstractFactory {
public:
virtual AbstractProductA* CreateProductA() const = 0;
virtual AbstractProductB* CreateProductB() const = 0;
virtual ~AbstractFactory() {}
};
// 具体工厂1
class ConcreteFactory1 : public AbstractFactory {
public:
AbstractProductA* CreateProductA() const override {
return new ProductA1();
}
AbstractProductB* CreateProductB() const override {
return new ProductB1();
}
};
// 具体工厂2
class ConcreteFactory2 : public AbstractFactory {
public:
AbstractProductA* CreateProductA() const override {
return new ProductA2();
}
AbstractProductB* CreateProductB() const override {
return new ProductB2();
}
};
// 客户端代码
int main() {
AbstractFactory* factory1 = new ConcreteFactory1();
AbstractProductA* productA = factory1->CreateProductA();
AbstractProductB* productB = factory1->CreateProductB();
productA->Operation();
productB->Operation();
delete productA;
delete productB;
delete factory1;
AbstractFactory* factory2 = new ConcreteFactory2();
productA = factory2->CreateProductA();
productB = factory2->CreateProductB();
productA->Operation();
productB->Operation();
delete productA;
delete productB;
delete factory2;
return 0;
} Singleton
Singleton 模式用于创建一个唯一的变量(对象)
通过维护一个 static 的成员变量来记录这个唯一的对象实例。
通过提供一个 staitc 的接口 instance 来获得这个唯一的实例
示例代码:
#include <iostream>
#include <mutex>
class Singleton {
private:
static Singleton* instance;
static std::mutex mutex;
protected:
// 构造函数为 protected,防止外部构造
Singleton() {
std::cout << "Singleton created." << std::endl;
}
public:
// 禁止拷贝构造函数和赋值操作
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
// 静态方法用于访问类的实例
static Singleton* getInstance() {
std::lock_guard<std::mutex> lock(mutex);
if (instance == nullptr) {
instance = new Singleton();
}
return instance;
}
void doSomething() {
std::cout << "Doing something." << std::endl;
}
};
// 初始化静态成员变量
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mutex;
int main() {
// 获取单例对象并调用方法
Singleton* singleton = Singleton::getInstance();
singleton->doSomething();
return 0;
}
Builder
Builder模式用于创建一个复杂的对象,其构建过程需要多个步骤。通过Builder模式,可以将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。
示例代码:
#include <iostream>
#include <string>
// 产品类
class Product {
public:
void addPart(const std::string& part) {
std::cout << "Part " << part << " added." << std::endl;
}
void show() {
std::cout << "Product completed!" << std::endl;
}
};
// 抽象建造者类
class Builder {
public:
virtual ~Builder() {}
virtual void buildPartA() = 0;
virtual void buildPartB() = 0;
virtual void buildPartC() = 0;
virtual Product* getProduct() = 0;
};
// 具体建造者类
class ConcreteBuilder : public Builder {
private:
Product* product;
public:
ConcreteBuilder() {
product = new Product();
}
~ConcreteBuilder() {
delete product;
}
void buildPartA() override {
product->addPart("A");
}
void buildPartB() override {
product->addPart("B");
}
void buildPartC() override {
product->addPart("C");
}
Product* getProduct() override {
return product;
}
};
// 指挥者类
class Director {
private:
Builder* builder;
public:
Director(Builder* bldr) : builder(bldr) {}
void construct() {
builder->buildPartA();
builder->buildPartB();
builder->buildPartC();
}
};
// 客户端代码
int main() {
ConcreteBuilder builder;
Director director(&builder);
director.construct();
Product* product = builder.getProduct();
product->show();
return 0;
} Prototype
Prototype (原型)模式提供了一个通过已存在对象进行新对象创建的接口(Clone)
示例代码:
#include <iostream>
#include <memory>
using namespace std;
// 抽象原型类
class Prototype {
public:
virtual ~Prototype() {}
virtual unique_ptr<Prototype> clone() = 0;
};
// 具体原型类
class ConcretePrototype : public Prototype {
private:
int value;
public:
ConcretePrototype(int val) : value(val) {}
ConcretePrototype(const ConcretePrototype& other) : value(other.value) {}
unique_ptr<Prototype> clone() override {
return make_unique<ConcretePrototype>(*this);
}
void setValue(int val) {
value = val;
}
int getValue() const {
return value;
}
};
// 客户端代码
int main() {
unique_ptr<Prototype> prototype = make_unique<ConcretePrototype>(100);
unique_ptr<Prototype> clonedPrototype = prototype->clone();
ConcretePrototype* concretePrototype = dynamic_cast<ConcretePrototype*>(clonedPrototype.get());
if (concretePrototype) {
cout << "Cloned value: " << concretePrototype->getValue() << endl;
}
return 0;
}
结构型模式
Bridge
Bridge模式允许抽象部分和实现部分可以独立变化
示例代码:
#include <iostream>
using namespace std;
// 实现接口
class AbstractionImp {
public:
virtual void operation() = 0;
virtual ~AbstractionImp() {}
};
// 具体实现A
class ConcreteAbstractionImpA : public AbstractionImp {
public:
void operation() override {
cout << "ConcreteAbstractionImpA operation." << endl;
}
};
// 具体实现B
class ConcreteAbstractionImpB : public AbstractionImp {
public:
void operation() override {
cout << "ConcreteAbstractionImpB operation." << endl;
}
};
// 抽象类
class Abstraction {
protected:
AbstractionImp* imp;
public:
Abstraction(AbstractionImp* implementation) : imp(implementation) {}
virtual void operation() = 0;
virtual ~Abstraction() {}
};
// 细化抽象
class RefinedAbstraction : public Abstraction {
public:
RefinedAbstraction(AbstractionImp* implementation) : Abstraction(implementation) {}
void operation() override {
cout << "RefinedAbstraction: ";
imp->operation();
}
};
// 客户端代码
int main() {
AbstractionImp* impA = new ConcreteAbstractionImpA();
AbstractionImp* impB = new ConcreteAbstractionImpB();
Abstraction* abstractionA = new RefinedAbstraction(impA);
Abstraction* abstractionB = new RefinedAbstraction(impB);
abstractionA->operation();
abstractionB->operation();
delete abstractionA;
delete abstractionB;
delete impA;
delete impB;
return 0;
}
Adapter(继承)
适配器模式(class)旨在将一个类的接口转换为客户端期望的另一个接口。通过这种方式,原本因为接口不兼容而无法一起工作的类可以协同工作。
通过继承来实现适配器功能
示例代码:
#include <iostream>
using namespace std;
// 目标接口(Target)
class Target {
public:
virtual void Request() {
cout << "Target: Default request." << endl;
}
};
// 适配者类(Adaptee)
class Adaptee {
public:
void SpecificRequest() {
cout << "Adaptee: Specific request." << endl;
}
};
// 适配器类(Adapter),继承自Target和Adaptee
class Adapter : public Target, private Adaptee {
public:
void Request() override {
// 调用适配者的特定方法
SpecificRequest();
}
};
// 客户端代码
int main() {
Target* target = new Adapter();
target->Request(); // 输出: Adaptee: Specific request.
delete target;
return 0;
} Adapter(组合)
适配器模式(object)通过组合的方式来实现适配器功能
示例代码:
#include <iostream>
using namespace std;
// 目标接口(Target)
class Target {
public:
virtual void Request() {
cout << "Target: Default request." << endl;
}
};
// 适配者类(Adaptee)
class Adaptee {
public:
void SpecificRequest() {
cout << "Adaptee: Specific request." << endl;
}
};
// 适配器类(Adapter),组合一个Adaptee对象
class Adapter : public Target {
private:
Adaptee* adaptee; // 组合适配者类
public:
Adapter(Adaptee* a) : adaptee(a) {}
void Request() override {
// 调用适配者的特定方法
adaptee->SpecificRequest();
}
};
// 客户端代码
int main() {
Adaptee* adaptee = new Adaptee();
Target* target = new Adapter(adaptee);
target->Request(); // 输出: Adaptee: Specific request.
delete adaptee;
delete target;
return 0;
} Decorator
Decorator (装饰器)模式允许在不修改原有类的情况下动态地为对象添加额外的功能。在C++中,装饰器通常通过继承来实现。
示例代码:
#include <iostream>
using namespace std;
// 抽象组件类(Component)
class Component {
public:
virtual void Operation() = 0; // 抽象操作方法
virtual ~Component() {}
};
// 具体组件类(ConcreteComponent)
class ConcreteComponent : public Component {
public:
void Operation() override {
cout << "ConcreteComponent: 执行基础操作。" << endl;
}
};
// 抽象装饰器类(Decorator)
class Decorator : public Component {
protected:
Component* component; // 维护一个Component的引用
public:
Decorator(Component* c) : component(c) {}
void Operation() override {
if (component) {
component->Operation();
}
}
};
// 具体装饰器类(ConcreteDecorator)
class ConcreteDecorator : public Decorator {
public:
ConcreteDecorator(Component* c) : Decorator(c) {}
void Operation() override {
Decorator::Operation(); // 调用原始组件的操作
AddedBehavior(); // 增加的新行为
}
void AddedBehavior() {
cout << "ConcreteDecorator: 添加额外的行为。" << endl;
}
};
// 客户端代码
int main() {
Component* component = new ConcreteComponent();
Component* decorator = new ConcreteDecorator(component);
decorator->Operation(); // 输出:执行基础操作,添加额外的行为
delete decorator;
delete component;
return 0;
} Composite
Composite (组合)模式允许树形结构的灵活构建
示例代码:
#include <iostream>
#include <vector>
using namespace std;
// 抽象组件类(Component)
class Component {
public:
virtual void Operation() = 0; // 纯虚函数,定义操作
virtual void Add(Component* component) {
throw std::runtime_error("Add operation not supported.");
}
virtual void Remove(Component* component) {
throw std::runtime_error("Remove operation not supported.");
}
virtual Component* GetChild(int index) {
throw std::runtime_error("GetChild operation not supported.");
}
virtual ~Component() {}
};
// 叶子节点类(Leaf)
class Leaf : public Component {
public:
void Operation() override {
cout << "Leaf: Performing operation." << endl;
}
};
// 组合节点类(Composite),可以包含多个子节点
class Composite : public Component {
private:
vector<Component*> children; // 存储子组件的集合
public:
void Operation() override {
cout << "Composite: Performing operation on children." << endl;
for (auto child : children) {
child->Operation(); // 递归调用子组件的操作
}
}
void Add(Component* component) override {
children.push_back(component);
}
void Remove(Component* component) override {
auto it = std::find(children.begin(), children.end(), component);
if (it != children.end()) {
children.erase(it);
}
}
Component* GetChild(int index) override {
if (index < children.size()) {
return children[index];
}
return nullptr;
}
};
// 客户端代码
int main() {
Component* leaf1 = new Leaf();
Component* leaf2 = new Leaf();
Component* composite1 = new Composite();
// 将叶子节点添加到组合中
composite1->Add(leaf1);
composite1->Add(leaf2);
// 执行组合的操作
composite1->Operation();
// 清理内存
delete leaf1;
delete leaf2;
delete composite1;
return 0;
} Flyweight
Flyweight 模式旨在通过共享大量细粒度对象来减少内存消耗。该模式通常用于需要大量重复对象的场景。
示例代码:
#include <iostream>
#include <unordered_map>
#include <string>
using namespace std;
// 享元基类(Flyweight)
class Flyweight {
public:
virtual void Operation(const string& extrinsicState) = 0; // 接收外部状态
virtual ~Flyweight() {}
};
// 具体享元类(ConcreteFlyweight),实现共享的操作
class ConcreteFlyweight : public Flyweight {
private:
string intrinsicState; // 内部状态(共享部分)
public:
ConcreteFlyweight(const string& state) : intrinsicState(state) {}
void Operation(const string& extrinsicState) override {
cout << "具体享元: 内部状态 = " << intrinsicState
<< ", 外部状态 = " << extrinsicState << endl;
}
};
// 不共享的享元类(UnsharedConcreteFlyweight),每个实例都有自己独立的状态
class UnsharedConcreteFlyweight : public Flyweight {
public:
void Operation(const string& extrinsicState) override {
cout << "不共享的享元: 外部状态 = " << extrinsicState << endl;
}
};
// 享元工厂类(FlyweightFactory)
class FlyweightFactory {
private:
unordered_map<string, Flyweight*> flyweights; // 享元池
public:
~FlyweightFactory() {
for (auto pair : flyweights) {
delete pair.second;
}
}
// 获取享元对象,如果不存在则创建新的
Flyweight* GetFlyweight(const string& key) {
if (flyweights.find(key) == flyweights.end()) {
flyweights[key] = new ConcreteFlyweight(key);
cout << "创建享元对象: " << key << endl;
}
return flyweights[key];
}
};
// 客户端代码
int main() {
FlyweightFactory* factory = new FlyweightFactory();
// 获取共享的享元对象
Flyweight* flyweight1 = factory->GetFlyweight("A");
Flyweight* flyweight2 = factory->GetFlyweight("B");
Flyweight* flyweight3 = factory->GetFlyweight("A"); // 重复的享元对象
// 使用共享的享元对象
flyweight1->Operation("外部状态1");
flyweight2->Operation("外部状态2");
flyweight3->Operation("外部状态3");
// 使用不共享的享元对象
Flyweight* unshared = new UnsharedConcreteFlyweight();
unshared->Operation("外部状态4");
delete unshared;
delete factory;
return 0;
} Proxy
Proxy 模式通过代理对象控制对实际对象的访问
示例代码:
#include <iostream>
using namespace std;
// 抽象主题类(Subject),定义公共接口
class Subject {
public:
virtual void Request() = 0;
virtual ~Subject() {}
};
// 真实主题类(ConcreteSubject),实现实际的业务逻辑
class ConcreteSubject : public Subject {
public:
void Request() override {
cout << "ConcreteSubject: Handling request." << endl;
}
};
// 代理类(Proxy),控制对ConcreteSubject的访问
class Proxy : public Subject {
private:
ConcreteSubject* realSubject;
public:
Proxy() : realSubject(nullptr) {}
~Proxy() {
if (realSubject) {
delete realSubject;
}
}
void Request() override {
if (!realSubject) {
realSubject = new ConcreteSubject(); // 延迟实例化真实对象
}
cout << "Proxy: Delegating request to ConcreteSubject." << endl;
realSubject->Request(); // 转发请求给真实对象
}
};
// 客户端代码
int main() {
Subject* proxy = new Proxy();
// 客户端通过代理来访问真实主题
proxy->Request(); // 输出代理类和真实类的操作
delete proxy;
return 0;
}
行为模式
Template
Template 模式可以让子类在不改变算法整体结构的前提下修改算法的某些步骤,从而实现代码复用和扩展。
示例代码:
#include <iostream>
using namespace std;
// 抽象类(AbstractClass),定义了模板方法以及抽象的原语操作
class AbstractClass {
public:
// 模板方法,定义算法的骨架
void TemplateMethod() {
Primitive1();
Primitive2();
}
// 原语操作1,子类需要实现
virtual void Primitive1() = 0;
// 原语操作2,子类需要实现
virtual void Primitive2() = 0;
virtual ~AbstractClass() {}
};
// 具体类1(ConcreteClass1),实现具体的原语操作
class ConcreteClass1 : public AbstractClass {
public:
void Primitive1() override {
cout << "ConcreteClass1: 实现Primitive1" << endl;
}
void Primitive2() override {
cout << "ConcreteClass1: 实现Primitive2" << endl;
}
};
// 具体类2(ConcreteClass2),实现具体的原语操作
class ConcreteClass2 : public AbstractClass {
public:
void Primitive1() override {
cout << "ConcreteClass2: 实现Primitive1" << endl;
}
void Primitive2() override {
cout << "ConcreteClass2: 实现Primitive2" << endl;
}
};
// 客户端代码
int main() {
AbstractClass* class1 = new ConcreteClass1();
AbstractClass* class2 = new ConcreteClass2();
// 使用模板方法执行算法
cout << "ConcreteClass1调用模板方法:" << endl;
class1->TemplateMethod();
cout << "\nConcreteClass2调用模板方法:" << endl;
class2->TemplateMethod();
// 释放内存
delete class1;
delete class2;
return 0;
} Strategy
Strategy (策略)模式使得算法可以在不影响客户端的情况下发生变化。
示例代码:
#include <iostream>
using namespace std;
// 策略接口类(Strategy),定义了算法接口
class Strategy {
public:
virtual void AlgorithmInterface() = 0; // 定义算法的接口
virtual ~Strategy() {}
};
// 具体策略A(ConcreteStrategyA),实现了具体的算法
class ConcreteStrategyA : public Strategy {
public:
void AlgorithmInterface() override {
cout << "执行算法 A" << endl;
}
};
// 具体策略B(ConcreteStrategyB),实现了另一种算法
class ConcreteStrategyB : public Strategy {
public:
void AlgorithmInterface() override {
cout << "执行算法 B" << endl;
}
};
// 上下文类(Context),持有一个策略对象,并使用它来完成具体的操作
class Context {
private:
Strategy* strategy; // 持有一个策略对象
public:
Context(Strategy* strategy) : strategy(strategy) {}
void DoAction() {
// 调用策略的算法接口
strategy->AlgorithmInterface();
}
// 设置新的策略
void SetStrategy(Strategy* newStrategy) {
strategy = newStrategy;
}
};
// 客户端代码
int main() {
// 创建具体策略
Strategy* strategyA = new ConcreteStrategyA();
Strategy* strategyB = new ConcreteStrategyB();
// 使用策略A
Context* context = new Context(strategyA);
context->DoAction(); // 输出:执行算法 A
// 切换为策略B
context->SetStrategy(strategyB);
context->DoAction(); // 输出:执行算法 B
// 清理内存
delete strategyA;
delete strategyB;
delete context;
return 0;
} State
State 模式允许对象在其内部状态改变时改变其行为,能够避免使用大量的条件语句判断状态。
示例代码:
#include <iostream>
using namespace std;
// 状态接口类(State)
class State {
public:
virtual void OperationInterface() = 0; // 定义状态相关的操作
virtual void ChangeState(class Context* context) = 0; // 改变上下文的状态
virtual ~State() {}
};
// 前置声明上下文类(Context)
class Context;
// 具体状态A(ConcreteStateA)
class ConcreteStateA : public State {
public:
void OperationInterface() override {
cout << "ConcreteStateA: 执行操作。" << endl;
}
void ChangeState(Context* context) override;
};
// 具体状态B(ConcreteStateB)
class ConcreteStateB : public State {
public:
void OperationInterface() override {
cout << "ConcreteStateB: 执行操作。" << endl;
}
void ChangeState(Context* context) override;
};
// 上下文类(Context),持有状态对象
class Context {
private:
State* state; // 当前状态对象
public:
Context(State* initialState) : state(initialState) {}
// 设置新的状态
void ChangeState(State* newState) {
state = newState;
}
// 执行状态相关的操作
void OperationInterface() {
state->OperationInterface();
}
// 调用状态的切换逻辑
void RequestChangeState() {
state->ChangeState(this);
}
};
// 状态转换实现
void ConcreteStateA::ChangeState(Context* context) {
cout << "从 ConcreteStateA 切换到 ConcreteStateB" << endl;
context->ChangeState(new ConcreteStateB());
}
void ConcreteStateB::ChangeState(Context* context) {
cout << "从 ConcreteStateB 切换到 ConcreteStateA" << endl;
context->ChangeState(new ConcreteStateA());
}
// 客户端代码
int main() {
// 创建初始状态为 ConcreteStateA
State* initialState = new ConcreteStateA();
Context* context = new Context(initialState);
// 执行操作并切换状态
context->OperationInterface(); // 输出: ConcreteStateA: 执行操作。
context->RequestChangeState(); // 切换到 ConcreteStateB
// 再次执行操作
context->OperationInterface(); // 输出: ConcreteStateB: 执行操作。
context->RequestChangeState(); // 切换回 ConcreteStateA
// 清理内存
delete context;
return 0;
} Observer
Observer (观察者)模式定义了对象间的一对多依赖关系,使得当一个对象的状态发生变化时,所有依赖于它的对象都能自动接收到通知并更新。它常用于构建事件驱动系统。
示例代码:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 抽象观察者类(Observer),定义了Update接口
class Observer {
public:
virtual void Update(int state) = 0; // 接收通知更新的方法
virtual ~Observer() {}
};
// 抽象主题类(Subject),管理观察者的注册和通知
class Subject {
private:
vector<Observer*> observers; // 存储观察者的列表
public:
// 注册观察者
void Attach(Observer* observer) {
observers.push_back(observer);
}
// 移除观察者
void Detach(Observer* observer) {
observers.erase(remove(observers.begin(), observers.end(), observer), observers.end());
}
// 通知所有观察者
void Notify(int state) {
for (Observer* observer : observers) {
observer->Update(state);
}
}
};
// 具体主题类(ConcreteSubject),继承自Subject
class ConcreteSubject : public Subject {
private:
int state; // 主题的状态
public:
int GetState() const {
return state;
}
void SetState(int newState) {
state = newState;
Notify(state); // 当状态改变时通知所有观察者
}
};
// 具体观察者A(ConcreteObserverA),实现Update接口
class ConcreteObserverA : public Observer {
public:
void Update(int state) override {
cout << "ConcreteObserverA: 观察到状态变化为 " << state << endl;
}
};
// 具体观察者B(ConcreteObserverB),实现Update接口
class ConcreteObserverB : public Observer {
public:
void Update(int state) override {
cout << "ConcreteObserverB: 观察到状态变化为 " << state << endl;
}
};
// 客户端代码
int main() {
// 创建具体主题对象
ConcreteSubject* subject = new ConcreteSubject();
// 创建两个具体观察者对象
Observer* observerA = new ConcreteObserverA();
Observer* observerB = new ConcreteObserverB();
// 注册观察者
subject->Attach(observerA);
subject->Attach(observerB);
// 改变主题状态,观察者将收到通知
subject->SetState(10); // 输出: ConcreteObserverA 和 ConcreteObserverB 都收到状态 10 的通知
// 移除一个观察者,并再次改变状态
subject->Detach(observerA);
subject->SetState(20); // 输出: 只有 ConcreteObserverB 收到状态 20 的通知
// 清理内存
delete subject;
delete observerA;
delete observerB;
return 0;
} Mediator
Mediator (中介者)模式通过消除对象之间的显式相互依赖,使这些对象彼此独立。这样,有助于避免对象之间的直接联系,有利于松耦合。
示例代码:
#include <iostream>
#include <string>
using namespace std;
// 前置声明
class Colleague;
class ConcreteColleagueA;
class ConcreteColleagueB;
// 中介者接口类(Mediator)
class Mediator {
public:
virtual void IntroColleague(Colleague* colleagueA, Colleague* colleagueB) = 0;
virtual void DoActionFromAtoB() = 0;
virtual void DoActionFromBtoA() = 0;
virtual ~Mediator() {}
};
// 同事接口类(Colleague)
class Colleague {
protected:
Mediator* mediator; // 持有一个中介者的引用
public:
Colleague(Mediator* mediator) : mediator(mediator) {}
virtual void Action() = 0;
};
// 具体同事类A(ConcreteColleagueA)
class ConcreteColleagueA : public Colleague {
public:
ConcreteColleagueA(Mediator* mediator) : Colleague(mediator) {}
void Action() override {
cout << "具体同事A正在执行自己的操作。" << endl;
}
void SendAction() {
cout << "具体同事A请求中介者将操作传递给同事B。" << endl;
mediator->DoActionFromAtoB();
}
};
// 具体同事类B(ConcreteColleagueB)
class ConcreteColleagueB : public Colleague {
public:
ConcreteColleagueB(Mediator* mediator) : Colleague(mediator) {}
void Action() override {
cout << "具体同事B正在执行自己的操作。" << endl;
}
void SendAction() {
cout << "具体同事B请求中介者将操作传递给同事A。" << endl;
mediator->DoActionFromBtoA();
}
};
// 具体中介者类(ConcreteMediator)
class ConcreteMediator : public Mediator {
private:
Colleague* colleagueA;
Colleague* colleagueB;
public:
void IntroColleague(Colleague* a, Colleague* b) override {
colleagueA = a;
colleagueB = b;
}
void DoActionFromAtoB() override {
cout << "中介者从A接收到请求,并要求B执行操作。" << endl;
if (colleagueB) colleagueB->Action();
}
void DoActionFromBtoA() override {
cout << "中介者从B接收到请求,并要求A执行操作。" << endl;
if (colleagueA) colleagueA->Action();
}
};
// 客户端代码
int main() {
// 创建中介者对象
ConcreteMediator* mediator = new ConcreteMediator();
// 创建两个具体的同事对象
ConcreteColleagueA* colleagueA = new ConcreteColleagueA(mediator);
ConcreteColleagueB* colleagueB = new ConcreteColleagueB(mediator);
// 通过中介者引入同事对象
mediator->IntroColleague(colleagueA, colleagueB);
// A 请求中介者通知 B
colleagueA->SendAction();
// B 请求中介者通知 A
colleagueB->SendAction();
// 清理内存
delete colleagueA;
delete colleagueB;
delete mediator;
return 0;
} Command
Command 模式将请求封装为对象,从而使你可以用不同的请求对客户进行参数化,将请求排队或者记录请求日志,并支持可撤销的操作。
示例代码:
#include <iostream>
using namespace std;
// 接收者类(Receiver),定义了具体的动作
class Receiver {
public:
void Action() {
cout << "Receiver: 执行操作" << endl;
}
};
// 命令接口类(Command),定义了一个执行操作的接口
class Command {
public:
virtual void Execute() = 0;
virtual ~Command() {}
};
// 具体命令类(ConcreteCommand),将接收者的操作封装为命令
class ConcreteCommand : public Command {
private:
Receiver* receiver; // 持有接收者的引用
public:
ConcreteCommand(Receiver* r) : receiver(r) {}
void Execute() override {
receiver->Action(); // 调用接收者的操作
}
};
// 调用者类(Invoker),调用命令对象执行请求
class Invoker {
private:
Command* command; // 持有一个命令对象的引用
public:
void SetCommand(Command* cmd) {
command = cmd;
}
void Invoke() {
if (command) {
command->Execute(); // 调用命令的执行方法
}
}
};
// 客户端代码
int main() {
// 创建接收者
Receiver* receiver = new Receiver();
// 创建命令并将接收者关联到命令
Command* command = new ConcreteCommand(receiver);
// 创建调用者并将命令传递给调用者
Invoker* invoker = new Invoker();
invoker->SetCommand(command);
// 调用者执行命令
invoker->Invoke();
// 清理内存
delete command;
delete invoker;
delete receiver;
return 0;
} Visitor
Visitor 模式将对象结构的操作与结构本身分离,可以在不改变对象结构的前提下定义新的操作。
示例代码:
#include <iostream>
#include <vector>
using namespace std;
// 前向声明
class ConcreteElementA;
class ConcreteElementB;
// 访问者接口类(Visitor)
class Visitor {
public:
virtual void VisitConcreteElementA(ConcreteElementA* element) = 0;
virtual void VisitConcreteElementB(ConcreteElementB* element) = 0;
virtual ~Visitor() {}
};
// 元素接口类(Element),定义接受访问者的方法
class Element {
public:
virtual void Accept(Visitor* visitor) = 0;
virtual ~Element() {}
};
// 具体元素A(ConcreteElementA),实现了接受访问者的方法
class ConcreteElementA : public Element {
public:
void Accept(Visitor* visitor) override {
visitor->VisitConcreteElementA(this);
}
string OperationA() const {
return "具体元素A的操作";
}
};
// 具体元素B(ConcreteElementB),实现了接受访问者的方法
class ConcreteElementB : public Element {
public:
void Accept(Visitor* visitor) override {
visitor->VisitConcreteElementB(this);
}
string OperationB() const {
return "具体元素B的操作";
}
};
// 具体访问者A(ConcreteVisitorA),实现访问操作
class ConcreteVisitorA : public Visitor {
public:
void VisitConcreteElementA(ConcreteElementA* element) override {
cout << "访问者A访问: " << element->OperationA() << endl;
}
void VisitConcreteElementB(ConcreteElementB* element) override {
cout << "访问者A访问: " << element->OperationB() << endl;
}
};
// 具体访问者B(ConcreteVisitorB),实现访问操作
class ConcreteVisitorB : public Visitor {
public:
void VisitConcreteElementA(ConcreteElementA* element) override {
cout << "访问者B访问: " << element->OperationA() << endl;
}
void VisitConcreteElementB(ConcreteElementB* element) override {
cout << "访问者B访问: " << element->OperationB() << endl;
}
};
// 客户端代码
int main() {
vector<Element*> elements = {new ConcreteElementA(), new ConcreteElementB()};
ConcreteVisitorA* visitorA = new ConcreteVisitorA();
ConcreteVisitorB* visitorB = new ConcreteVisitorB();
// 访问者A访问所有元素
cout << "访问者A开始访问:" << endl;
for (Element* elem : elements) {
elem->Accept(visitorA);
}
// 访问者B访问所有元素
cout << "\n访问者B开始访问:" << endl;
for (Element* elem : elements) {
elem->Accept(visitorB);
}
// 清理内存
for (Element* elem : elements) {
delete elem;
}
delete visitorA;
delete visitorB;
return 0;
}