2024软件系统设计期末复习
2024软件系统设计期末复习
出分了,今年这课给分极其诡异,我不做评价。总之还是纪念一下期末周大家一起快乐复习(破防)的日子。
以下依旧是集体劳动的成果。感谢文档创作者金君、张君、刘君等。
1.Software Architecture in General
What is software architecture
- SEI
- 程序或计算系统的软件系统架构是系统的一个或多个结构(Structure),包含了程序的元素(Elements)和他们的外部可见元素属性(Properties)以及元素之间的关系(Relationships)
- IEEE
- 一个系统的基本组织,包含了它的所有组件(Components)、组件之间的关系、环境以及指导该系统的设计(Design)和演化(Evolution)的原则(Principle)
架构和结构:包括结构,不仅是静态,还包括行为
架构与设计:架构在设计早期,高抽象层次的设计
【2019】Architecture,structure和Design的区别?
- Design 包含 Architecture,Architecture 包含 Structure
- 结构是静态的、逻辑的,是关于系统如何构成的
- 体系结构除包含架构,还会包含组件之间的相关的关系结构,并定义一些动态的行为。
- 体系结构是关于软件设计的,所有体系结构都是设计,但是不是所有的设计都是体系结构,体系结构是软件设计的一个部分
What does a software architect do
- 联络
- 在客户、技术团队和商业/需求分析师之间
- 与管理层或营销层
- 软件工程
- 软件工程最佳实践
- 技术知识
- 技术领域很深的理解
- 危机管理
- 与设计、技术选择有关的危机
Where do architectures come from【2015】
- NFRs(Non-Functional Requirements,非功能性需求)
- ASRs(Architecturally Significant Requirements,架构攸关需求)
- 质量需求(quality requirements)
- 系统利益相关者(stakeholders)
- 开发组织(organizations)
- 技术环境(Technical Environments)
Architecture(4+1)views(K.Kruchen 4+1 views)
逻辑视图****(Logical View):描述了体系结构中的在体系结构上明显重要的元素和他们之间的关系。
过程视图****(Process View):描述了体系结构中的并发和体系结构元素之间的交流。
物理视图****(Physical / Deployment View ):描述了主要过程和组件是如何被映射到硬件上的。
发展视图****(Development / Implementation View):描述了软件组件的内部组织,比如使用配置管理工具存储
架构用例(Use Case):描述了体系结构的需求,往往关联超过一个常规视图,是质量属性方案
Architectural Activities
- 为系统创建业务用例
- 理解需求
- 构造并选择架构
- 与利益相关者交流架构(包括开发者)
- 分析评估架构
- 整体方法
- 质量具体技术
- 实现结构
- 确保与架构一致
Architectural process
- 通过 StackHolder 获取到 ASRs(架构攸关需求)
- 通过分析得到高优先级质量属性解决方案(Prioritized Quality Attribute Scenarios)和需求和约束(Requirements and Constraints)
- 将上述部分,结合模式和策略,综合可以得到架构的设计
- 根据架构的设计得到由模式决定的候选视图的示意图,之后完成文档化
- 选择、组合视图,将文档进行进一步的评估,这一部分需要 StackHolder 的参与、也需要 Prioritized Quality Attribute Scenarios 和文档等作为参考。
Briefly describe the general activities in a software architecture process, and the major inputs and outputs at each activity.
- 识别ASRs
- 输入:无
- 输出:优化的质量属性场景
- 架构设计
- 输入:优化的质量属性场景、需求和约束、模式和决策
- 输出:一组候选视图的草图(模式决定)
- 架构文档化
- 输入:一组模式决定的草图(由模式决定)
- 输出:View & Beyond
- 架构评估
- 输入:View & Beyond、优化的质量属性场景
- 输出:View & Beyond
Software architecture knowledge areas
- 软件设计的基本观念(软件开发的生命周期,设计过程等)
- 关键问题(技术):并发性、事件的控制和处理、分发、异常处理、交互系统、持久性
- 软件结构和架构:体系结构样式和模式(宏观体系结构),设计模式(微观体系结构)
- 软件设计方法:架构方法(如+ADD)设计方法(如动态系统开发方法)
- 软件设计质量分析和评估:质量属性、质量分析和评估的方法技术和工具、度量
- 设计建模和表现方式:架构设计符号(ADL),UML,设计文档(Views&Beyond),其他
2.Quality Attributes
What are Software Requirements
- 功能需求 Functional requirements
- 功能需求说明系统必须做什么,并说明系统如何为涉众提供价值
- 功能需求是指系统的行为。
- 功能是系统完成其预期工作的能力,例如,允许学生在线注册。
- 功能可以通过使用任意数量的可能结构来实现。
- 功能在很大程度上独立于结构,因为它可以作为一个单独的单片系统存在,而不需要任何内部结构。
- 质量需求 Quality requirements(NFRs)
- 质量要求是整个系统的理想特性。系统应该在其功能需求之上提供的质量属性。
- 质量要求是功能需求或整个产品的资格。
- 如果质量属性很重要,那么软件架构会限制将功能分配(映射)到各种结构上。
- 约束 Constraints
- 约束是零自由度的设计决策
- 约束是预先指定的已经做出的设计决策。
- 通过接受设计决策并将其与其他受影响的设计决策进行协调,可以满足约束
【2022】Software requirements, Quality attributes, ASRs 的区别和联系
- 软件需求包括功能性需求和非功能性需求(又称质量需求)
- 质量属性是由软件的业务目标所决定,在功能性需求的基础上提供的整个系统的合乎需求的特性,是非功能需求的一种反应。
- ASRs架构攸关需求是对于体系结构有着深远影响的需求,如果没有这样的需求,架构可能会有很大的不同。肯定是软件需求的一部分。
Quality Attributes
Internal vs external attributes(from gpt)
内在属性是指那些可以在软件内部直接衡量和评估的特性。这些属性通常与软件的内部结构和代码有关。常见的内在属性包括:模块性(Modularity)、可重用性(Reusability)、可维护性(Maintainability)、可测试性(Testability)、互操作性(Interoperability)
外在属性是指那些从软件系统外部衡量和评估的特性,通常与用户体验和系统整体运行效果相关。常见的外在属性包括:可用性(Availability)、性能(Performance)、易用性(Usability)、互操作性(Interoperability)
zh:外部,系统当成黑盒,用户和系统交互体验,可用性、性能、安全等;内部,只有了解系统内部的开发人员能感知到,所关注 互操作性、可修改性、可测试性等
- Adaptability(适应性) 系统适应变化的能力。
- Extensibility(可扩展性) 系统在不影响现有功能的情况下增加新功能的能力。
- Availability(可用性) 系统在需要时可用的程度。
- Modularity(模块性) 系统被组织成模块化结构的能力。
- Configurability(可配置性) 系统根据用户需求进行配置的能力。
- Portability(可移植性) 系统从一个环境迁移到另一个环境的能力。
- Flexibility(灵活性) 系统适应不同条件或需求的能力。
- Reusability(可重用性) 组件或代码在不同情境下重复使用的能力。
- Interoperability(互操作性) 不同系统或组件之间协同工作的能力。
- Testability(可测试性) 系统进行测试的能力。
- Performance(性能) 系统执行任务的速度和效率。
- Auditability(可审计性) 系统记录和审查的能力。
- Reliability(可靠性) 系统在规定条件下持续运行的能力。
- Maintainability(可维护性) 系统进行维护和升级的容易程度。
- Responsiveness(响应性) 系统对用户输入的响应速度。
- Manageability(可管理性) 系统进行管理的容易程度。
- Recoverability(可恢复性) 系统从故障中恢复的能力。
- Sustainability(可持续性) 系统长期运行和维护的能力。
- Scalability(可扩展性) 系统处理增长的工作量的能力。
- Supportability(可支持性) 系统获得支持和维护的能力。
- Stability(稳定性) 系统在长时间运行中保持性能的能力。
- Usability(易用性) 系统对用户友好和易于使用的程度。
- Security(安全性) 系统保护数据和资源免受未授权访问的能力。
Modeling quality attribute scenaris
Source, stimulus, artifact, environment, response, response measure
- 刺激(Stimulus):到达系统时需要考虑的条件
- 刺激源(Source of Stimulus):产生刺激的实体(人,系统或任何其他触发),可能是输入、信息等,对当前的状态的一个变化
- 响应(Response):刺激到来后工件开展的行为
- 响应度量(Response Measure):对刺激的响应以某种方法进行测量,以便可以测试需求(比如多长时间系统有反馈)
- 环境(Environment):发生刺激时系统的状况,例如系统正常运行、系统过载、 系统受到攻击、系统网络出现故障等
- 工件(Artifact):完成需求的整个系统或者系统的一部分(软件制品)
答题总结
availability:detect faults(heartbeat、timestamp)
Availability
可用性是应用程序的关键要求,以所需的可用时间来度量。
来源:内部/外部:人员、硬件、软件、物理基础设施、物理环境
刺激:故障:遗漏、崩溃、时间错误、响应错误
工件:处理器、通信渠道、持久存储、进程
环境:正常操作、启动、关闭、维修模式、降级操作、过载操作
响应:
- 防止故障变成失败
- 检测故障:
- 记录故障
- 通知适当的实体(人员或系统)
- 从故障中恢复:
- 禁用引起故障的事件源
- 在进行修复时暂时不可用
- 修复或掩盖故障/失败或控制它造成的损害
- 在进行修复时以降级模式运行
度量:
- 系统必须可用的时间或时间间隔
- 可用性百分比(例如,99.999%)
- 检测故障的时间
- 修复故障的时间
- 系统可以在降级模式中运行的时间或时间间隔
- 一定类别的故障,系统防止或处理而没有失败的比例(例如,99%)或速率(例如,每秒高达100次)
Interoperability
互操作性是指两个或多个系统可以在特定的上下文中通过接口有效交换有意义的信息的程度,包括语法可操作性(交换数据的能力)和语义可操作性(能够正确解释数据)。互操作性需要确定谁,什么以及在什么情况下(上下文)。
影响因素:发现(发现服务位置、身份和接口)、处理响应。
Modifiability
可修改性涉及到更改以及进行更改所需花费的时间或金钱,包括这种可变更性影响其他功能或质量属性的程度。
影响因素:变更是什么?变更可能性?何时谁进行变更?变更成本?
Performance
性能与时间有关,和系统满足时序要求的能力有关(单位时间能做多少事情)。
影响要素:处理时间(正在相应)和阻塞时间(无法相应)。
Security
安全性衡量系统保护数据和信息免遭未授权应用的能力,同时仍提供对授权人员和系统的访问权限。
影响要素:机密性(防止未授权访问)、完整性(防止未授权操纵)、可用性(系统可供合法使用)。
Testability
可测试性是指可以使软件通过(通常是基于执行)测试来证明其故障的难易程度。
Usability
易用性与用户完成所需任务的难易程度以及系统提供的用户支持的类型相关。
影响因素:学习系统功能、有效使用系统、最小化错误影响、使系统适应用户需求、增强信息和满意度。
Checklist for architecture design decisions
How to gather and identify ASRs
ASR: Architecturally significant requirements
Requirements, Interviews, Business goals, Utiliy tree
- 从需求文档中收集 ASR:可以使用“MoSCoW”样式或用户故事来收集需求 (不过难以收集质量需求),但其中大部分的内容都不会影响体系结构,对架构师有用的部分甚至没有出现在需求文档中。
- 通过采访涉众来收集 ASR:可以使用质量属性工作坊(QAW)
- QAW 演示和介绍
- 业务任务介绍
- 架构计划介绍
- 架构驱动程序的识别
- 场景集思广益:每一个利益相关者表达一个场景
- 方案合并(合并类似方案)
- 方案优先级(通过投票)
- 方案细化
- 通过了解业务目标来收集 ASR
- 通过质量属性实体树(Utility)来管理 ASR:使用方案量化描述需求后,逐渐对质量需求进行分解细化,直到含有量化指标为止。
3.Architecture Patterns
Architecture Patterns 架构模式
- 架构模式是在实践中反复发现的一套设计决策,具有允许重复使用的已知属性,并且描述了一类架构。
- 架构模式关联了如下三种角色:
- 背景(context):世界上经常发生问题的场景。
- 问题(problem):在给定上下文中出现经过适当概括的问题。
- 解决方案(Solution:Element + Relations + Constraints):针对问题的成功的经过适当抽象的解决方案。
- 模式是在实践中发现的
- 模式不是发明的,而是发现的。
- 永远不会有一个完整的模式列表。
Module Patterns 模块模式
分层模式 Layered Pattern/micro-kernel pattern
分层模式用来构造可以分解为子任务组的程序,每个子任务组都处于一个特定的抽象级别,每层都为下一个提供更高层次的服务。分层模式的关键点在于确定依赖,核心是关注点分离(必须逐层访问)
影响的质量属性:可修改性、可模块化、可维护性、可复用性。
上下文:一般桌面应用、Web(OSI 的七层网络模型)。
优点:高内聚、松耦合、易于维护
缺点:降低系统的性能,导致级联修改增加开发成本。
Context:系统模块可以独立开发和维护。
Solution:分层模式将软件划分称为层的单元。每一层都是一组模块,提供了一组内聚的服务。层的使用必须是单向的(逐层访问)。
- 分层模式的解决方案
- 分层模式变体
左侧不是分层模式,形成环形依赖(没有实现关注点分离),是软件的坏味道。
右侧在 D 不期待 A 的结果且 D 不期待 B 的结果时是分层模式,但是在严格意义和其他场景中不是分层模式
- 基于分层模式的系统实例
OSI 的七层网络模型
Component-Connector Patterns 组件-连接器模式
https://blog.csdn.net/m0_64536054/article/details/135018189
Broker pattern, Model-view-controller pattern, Pipe-and-filter pattern, Client-server pattern, Peer-to-peer pattern,Service-oriented pattern, Publish-subscribe pattern, Share-data pattern
代理体系结构模式可以用于构建分布式软件系统,其中具有通过 RMI 交互的分离组件,代理组件负责协调通信,如转发请求,以及传输结果和异常。
代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
上下文:多个同步或异步交互的远程对象组成的系统。
解决方案:通过提供隔离通讯相关的代理,将系统通信功能与主应用程序分开
优点:提高了 Client 和 Server 之间的交互性,提高可伸缩性和可扩展性;整体大集群的性能可能会提高(QPS 等提高),但是局部单点性能会下降,多次网络请求、多次匹配,有可能会抵消。
缺点:代理增加前期复杂度、可能成为通信的屏障、可能成为安全攻击的目标、难以测试。
Context:许多系统是由分布在多个服务器上的服务集合构建成的。需要了解服务如何相互连接、相互操作、交换信息。还需要关心服务的可用性。
Problem:如何构建分布式软件,使服务用户不需要知道服务商的性质和位置。
Solution:插入一个代理。将client和server分开。当client需要服务时,可以通过服务接口查询代理,然后代理将client的请求转发给处理该请求的server。
- 代理模式的解决方案
- 代理模式的概述图
使用运行时、动态、相互之间的关系来审视,集成到了开发框架中,也是分层架构 的变种(强调模块间约束关系,model 不可以直接返回到 controller),分为 model(业务逻辑)、view(处理用户展示,接收用户操作)、controller(对用户操作进行处理,将信息通知给 model)
优点:耦合性低,重用性高,生命周期成本低,部署快,可维护性高,方便管理
缺点:没有明确定义,不适于中小型应用程序,增加实现复杂度,视图和控制器过于紧密,视图对模型访问低效
- MVC 模式的解决方案
- MVC 模式的概述图
【2021】设计一个基于管道-过滤器模式的、输入文本文件、输出排序后的无重复的单词列表的程序。
- 用组件部分和连接器画出程序图。
- 画出组件的类图。
- 用 Java 实现每个类。
- 指出你的代码和 1、2 中图的映射。
wjj:FileToObject——拆分——排序——去重
管道和过滤器模式应用在顺序处理结构中,有一系列 filter 体现依赖关系。
Filter:相当于 Component,起数据处理、计算作用,每个 Filter 有 input 和多个output,将数据处理后传递给后续部分。
Pipe:相当于 Connector,连接 filter,将 output 导入到其他的 filter 的 input 中去,不会独立存在。
缺点:不适用于互动式系统,过多的过滤器导致大量的计算开销。
- 管道和过滤器模式的解决方案
- 管道和过滤器模式的概述图
每一个组件表示 filter,连接组件的部分是 pipe,任何一个 filter 都依赖于前一个 filter 的输出(没有其他机会接收外部交互),不适合交互的场景(破坏依赖关系)。
客户端-服务器模型是一种分布式应用程序结构,它在资源或服务(称为服务器)和服务请求者(称为客户端)的提供者之间划分任务或工作负载。客户端和服务器通常通过计算机网络在单独的硬件上进行通信,但客户端和服务器可能位于同一系统中。服务器主机运行一个或多个与客户共享资源的服务器程序。客户端不共享其任何资源,但请求服务器的内容或服务功能。因此,客户端启动与等待传入请求的服务器的通信会话。使用客户端-服务器模型的计算机应用程序的示例是电子邮件,网络打印和万维网。 包含了两类不同的 Component,没有 broker 可以动态改变 Client 和 Server 的关系, 成对的关系相对固定。
包含了两类不同的 Component,没有 broker 可以动态改变 Client 和 Server 的关系,成对的关系相对固定。
上下文:Windows 的客户端应用(桌面应用)。
缺点:服务器成为性能瓶颈、可能单点失效、决定在哪里实现功能的决定也是复杂的(并且难以修正。)
- 客户端-服务器模式的解决方案
- 客户端-服务器端的概述图
ATM 验证身份,某一个验证 Server 可以给很多设备提供服务。
ATM 操作安全监控、盗刷之类,通过 monitoring 可以发现问题找到记录。
对于银行工作人员,需要添加新的业务,policy 发生变化,银行工作人员可以定义 ATM 的操作。
银行负责安全金融的可以根据 ATM、对照用户操作行为是否有安全隐患,多对多。
点对点模式中的组件,可能这一时刻为提供者,下一时刻是消费者(对等的)。同时点对点模式不仅仅提供服务,还能提供物流,每个 peer 可能有一个规定对的连接数。
对等(P2P)计算或网络是分布式应用程序体系结构,用于在对等体之间划分任务或工作负载。同行在申请中享有同样的特权,等同参与者。据说它们形成了节点的点对点网络。
上下文:分布式应用程序体系结构,应用于对等体之间划分任务或工作负载。 缺点:安全性管理、数据持久化、数据/服务可用性(availability)、备份、修复更 复杂、小型点对点系统不能持续实现质量目标,类似性能(performance)和可用性 (availability)
上下文:分布式应用程序体系结构,应用于对等体之间划分任务或工作负载。
Context:分布式计算实体——既提供资源又消耗资源,是对等的,需要合作与协作
Problem:如何将一组对等的分布式实体通过协议相连接
Solution:组件作为对等实体直接交互,对等通信是一种请求/回复交互
缺点:安全性管理、数据一致性、数据持久化、数据/服务可用性(availability)、备份、修复更复杂、小型点对点系统不能持续实现质量目标,类似性能(performance)和可用性(availability)
- 点对点模式的解决方案
- 点对点模式的概述图
面向服务的体系结构(SOA)是一种软件设计风格,其服务通过应用程序组件,通过网络上的通信协议提供给其他组件。
面向服务的体系结构的基本原则独立于供应商,产品和技术。服务是一个独立的功能单元,可以远程访问并独立操作和更新,例如在线检索信用卡对帐单。
面向服务的模式是 Broker Pattern 的延伸,Component 包含服务提供者、服务消费者、ESB(企业服务总线)、企业服务组件、连接处理(注册、发现),Connector 包含 SOAP、REST、Asynchronous messaging connector。
Context:许多服务是由服务提供者提供,服务消费者消费。服务消费者只需要理解并使用服务,而不需要了解服务的详细实现。
Problem:如何支持在不同平台用不同语言编写的由不同组织提供的分布式组件的互操作性。
Solution:SOA描述了提供/使用服务的分布式组件的集合。服务使用者被连接到服务提供者,可以使用中间组件连接(例如ESB、注册表)。
缺点:构建复杂、无法管理独立服务的演化、服务可能成为性能瓶颈(无法提供性 能保障)、使用中间件导致的性能开销(Overhead)。
- 面向服务的模式的解决方案
- 面向服务的模式的概述图
Subscribe 对 Publish 进行注册,某个 Publisher 发布自己的消息可能订阅其他的消息(朋友圈微博)。随着订阅的增加,可能会导致性能的延迟(Subscriber 数量订阅越多性能下降)
在软件体系结构中,发布-订阅是一种消息模式,其中消息的发送者(称为发布者)不将消息直接发送到称为订阅者的特定接收者,而是将发布的消息送到连接器中(不知道有哪些订阅者)。类似地,订户表达对一个或多个类的兴趣并且仅接收感兴趣的消息,会接受到连接器的通知,而不知道哪些发布者(如果有的话)存在。
传统操作系统使用事件驱动方式来管理。
Context:有许多独立的生产者和消费者相互作用。生产者和消费者的数量和性质没有预先设定。
Problem:如何创建集成,支持生产者和消费者之间的信息传输。(生产者和消费者可能都不知道彼此的存在)
Solution:组件通过已经发布的消息进行交互。订阅者组件可以订阅一组事件,发布服务器组件通过宣布事件将事件放置在总线上,然后连接器将这些事件传递给已对这些事件感兴趣的订阅者组件。
优点:松耦合、可伸缩性、此模式提供更高的网络可扩展性和更动态的网络拓扑,从而降低了修改发布者和已发布数据结构的灵活性。
缺点:通常会增加延迟并对消息传递时间的可伸缩性和可预测性产生负面影响。对消息排序的控制较少,并且不保证消息的传递。
- 发布-订阅模式的解决方案
- 发布-订阅模式的概述图
中间安全数据会被很多人共享登录访问。
Context:各个计算组件需要共享和操作大量的数据。
Problem:系统如何存储和操作由多个组件同时共享访问的数据?
Solution:在共享数据模式中,交互是由多个数据访问器和至少一个共享数据存储器之间的持久数据交换组成。交换可以由访问器或存储器发起,连接器类型是数据读写。
一致性:CAP 原则(定理):在一个分布式系统中,一致性(Consistency)、可用性 (Availability)、分区容错性(Partition Tolerance),需要平衡三者。
一致性实现:最终一致性(不保证任何时间数据访问都一致但是保证最终结果要一致)、互联网不可能牺牲可用性来保障一致性(信号要求高),因此设计难度非常大。
缺点:共享数据模型可能存在性能瓶颈、可能存在单点失效、数据的生产者和消费者紧密耦合、中心点被攻击有安全风险、对安全性数据而言强调一致性,如果副本有一段时间不一致可能会成为漏洞(保证任何时刻访问数据都是一致的)。
- 共享数据模式的解决方案
- 共享数据模式的概述图
Allocation Patterns
Map-reduce pattern, Multi-tier pattern
映射-规约模式 Map-Reduce Pattern
Map 负责对数据进行抽取所需的信息,完成信息转换。可以有很多个 Map,每个 Map 处理的数据工作内容不一样,他们互相独立运行。Reduce 负责进行合并,产出最终的答案。
典型示例(词频统计):每个 Partition 对应一个 Map,每个 Map 分别完成词汇词频的统计,最后有 Reduce 合并后进行排序。
Context:企业需要快速分析他们产生或访问的大量数据。
缺点:如果没有足够大的数据集,那么 Map-Reduce 的开销是不能被接受的;如果不能将数据集切分成相似大小,那么并行的好处会消失;多次归纳是难以编排的。
- Map-Reduce Pattern 的解决方案
- Map-Reduce Pattern 的概述图
多层模式 Multi-Tier Pattern
Layer 是真实存在的,这里的层是逻辑的组合,没有层次模式的强依赖关系,在不同的部署环境中分层不同,但是软件完成内容一致。
许多系统的执行结构被组织成一组逻辑组件。每个分组被称为一个层。将组件分组到层中可能基于各种标准,例如组件的类型、共享相同的执行环境或具有相同的运行时目的。
Context:分布式部署中,通常需要将系统的基础设施分发到不同的子集中。
Problem:如何将系统分割成一些计算上独立的结构。
Solution:许多系统的执行结构被组织成一组逻辑组件,每个分组被称为一个层。层,是一个软件组件的逻辑分组。
上下文:旅行社。
缺点:大量的前期成本和复杂性。
- 多层模式的解决方案
- 多层模式的概述图
分层模式和多层模式的区别【2018】
- 分层模式是⼀种模块视图;多层模式是⼀种分配视图。
- 分层强调的是单向的层与层之间的关系,每层是⼀个整体;多层的层是分组,将组件按照类型、环境等进行分类得到的分组,包含很多组件,允许相互访问
- 分层强调的是代码的组织形式;多层强调的是代码的执行位置
- 分层的每个层通常在同⼀机器运行;多层的每个层可能在不同的机器上运行
架构设计与策略具体应用
以 Layered Pattern 为例,目的是为了提高语义连贯性和限制依赖。系统设计全过程如下。首先目前系统如下所示:
椭圆形表示一个 Tactics,添加一个策略可能对某一个质量属性有贡献,但是会产生其他的负面影响(系统复杂度、资源影响、性能等)
圆矩形表示添加策略后可能会导致的影响/后果。
假设对性能非关注,那么我们进行单独的成本和资源利用率的设计考量如下:
为了提高资源的利用率,引入调度机制,而一切设计的可行性判断是根据 ASR 进行(分解到负面影响系统可以忍受则停止、没有足够人力物力则停止),以上整个过程汇不断迭代知道妥协(每一个 Tactic 的引入都会增加系统复杂度和规模)。
最终设计如下:
Patterns vs. Tactics(模式 vs. 战术)
- 战术比模式简单
- 战术是一种设计决策,而模式是一组设计决策的集合
- 都是架构师的基础工具
- 战术是设计的建筑基石
- 大多模式包含几个不同的战术。例如分层模式包含增加内聚,降低依赖的战术
- 大多数模式也会包含其他模式
https://blog.csdn.net/qq_44202160/article/details/124076040
描述架构模式和战术的联系,列出4个战术名并描述他们的用途【2015】
架构模式:是在实践中反复发现的一套设计决策,具有允许重复使用的已知属性,并且描述了一类架构
战术:影响质量属性响应控制的设计决策,例如冗余。
关系:
- 战术是实现架构模式的具体方式,可以帮助开发人员更好地理解和应用架构模式
- 大多数模式由几个不同的战术实现
- 都是架构师的主要工具
- 像模式一样,策略也可以由其他策略组成
战术名:
- 减小模块大小:用拆分模块的方式尽可能地控制包的大小,让每个包拥有的功能尽可能小,降低修改成本。
- 延迟绑定:在生命周期中与初始定义阶段不同的阶段绑定某些参数的值,提高可修改性。
- 检测攻击:通过检测入侵、检测服务拒绝、哈希校验等策略来检测攻击,提高安全性。
- 限制复杂度:通过限制结构的复杂性来避免、减少或解决组件之间的依赖关系,提升可测试性。
4.Designing Architecture
General Design Strategy 通用设计策略
抽象、分解、分治、生成和测试、迭代、重用
ADDGIR :D
Categories of design decisions
职责、协调、数据、资源、元素映射、绑定时间、技术
软件设计的通用策略,并为每个战略给出简洁的软件架构示例(如ADD)【2022】【2021】【2017】【2019】TODO
- 抽象:使用抽象让设计师关注本身结构而不关心实现,比如将系统抽象为组件和连接件或抽象为模块。
- 分解:针对某一个系统关注点分解后处理,比如将整个系统分解或将某个模块分解。
- 分治:将每个模块分别处理
- 生成与测试:将一个特定的设计看作是一个假设;根据测试路径生成测试用例。
- 迭代与细化:使用迭代的方法,ADD方法多次迭代直到满足所有ASR
- 复用元素:重用在设计过程中出现了可以复用的元素,重用现有架构
属性驱动设计(Attribute-Driven Design, ADD)
ADD 的输入:需求
ADD 的输出:
- 软件元素:完成各种决策和职责、定义属性并与其他软件元素相关以组成系统架构的计算或开发工件。
- 角色:一组相关的职责。
- 职责:软件提供的功能、数据或信息。
- 属性:有关软件元素的附加信息。
- 关系:两个软件元素之间如何相互关联和交互的定义。
简单记忆:元素和元素之间的联系,职责和属性。
step 1:确定有足够的需求信息
- 系统涉众已经根据业务和任务目标确定了需求的优先级,同时您可以确定设计期间需要重点关注的系统元素。
- 确认是否有关于系统质量属性要求的足够关系:刺激-反应图(Stimulus-Response)
step 2:选择要分解的系统要素
- 如果是第一次设计未开发的系统时,需要将全部需求分配给系统。
- 如果是完善部分设计的系统时(系统已经被划分为多个元素,并分配需求),则从上述元素中选择一个元素作为关注点。
step 3:确定所选元素的 ASR
根据每个需求对涉众的重要程度(高、中或低),以及对架构的潜在影响(高、中或低)对所有的需求进行排名,得到(H,H)等二元组。
step 4:选择符合 ASR 的设计
step 4.1:找出设计问题
如何解决设计中的 ASR?如何将关注点划分为几个子关注点?
step 4.2:列出子关注点替代模式/策略
对于列表中的每个模式,都应该识别每个区分模式的区分参数(帮助在模式和策略中选择)、估计区分参数的值。
step 4.3:从清单中选择模式/策略
使用每种模式时有哪些权衡?模式之间的结合程度如何?是否有任何模式互斥?
step 4.4:确定模式/策略与 ASR 之间的关系
考虑到目前为止确定的模式/策略,并确定他们之间的关系(使用表格描述),所选的模式的组合可能会构成新的模式。
step 4.5:记录初步的架构视图
通过开始记录不同的架构视图来描述模式,但不要求在此阶段创建完整记录的架构视图。
step 4.6:评估并解决不一致问题
根据架构驱动来评估设计的合理性
确定是否有架构驱动没有被考虑到
评估替代模式或者使用其他策略
将当前元素设计与体系结构中其他元素的设计进行评估,并解决所有的不一致。
step 5:实例化架构元素并分配职责
- 实例化每一个所选的元素的实例
- 根据子元素类型来分配具体的职责
- 在子元素之间分配与父元素相关联的职责
- 分析并记录所做的设计决策
step 6:为实例化元素定义接口
接口描述了提供(Provide)和需要(Requires)两种假设,即软件元素之间的互相联系,可以通过功能要求、观察信息传递消耗等方法。
step 7:验证和完善需求
- 验证分配给父元素的所有需求是否被分配给一个或多个子元素。
- 将分配给子元素的所有的职责转换为各个元素的功能需求。
step 8:重复进行2-7,直到满足所有的 ASR
5.Documenting Architecture
Why to document software architecture?
- 交流和社交化架构设计决策
- 帮助理解和评估架构设计决策
- 刷新设计师对某些决策的记忆
- 培训架构设计人员
- 支持地理位置分散的团队
- used for several activities:
- 架构设计分析
- 工作分解和分配
- 部署后维护
- 软件架构文档提供了维护和修改决策的框架
Challenges in documenting architecture
- 没有普遍接受的记录软件架构的标准或方法
- 记录大型系统的架构可能是一项耗时且重要的任务
- 对用于记录架构的视图的数量和性质没有达成共识,是资源密集型活动
- 迫在眉睫的最后期限和不断发展的架构性质不利于架构文档的流通
- 缺乏全面的符号和工具
What to document?
- 组件接口和依赖项
- 子系统约束
- 测试场景
- 围绕设计决策的上下文信息
Factors affect the decision of what to document
- 被记录的架构的复杂性
- 应用程序的寿命
- 基于涉众对文档的预期使用
7 Rules for Architecture Documentation
- 从读者的角度撰写文档
- 避免没有意义的重复
- 避免模糊性
- 使用标准的文档组织方式
- 记录理由
- 保持文档最新但不要太最新
- 审查文件是否适合用途
Views
Styles vs Patterns vs Views
- 架构风格
- 是元素和关系类型的特殊化,以及如何使用它们的一组约束
- 不包含具体的上下文和问题,侧重于架构方法,对特定风格何时有用或无用提供更轻量级的指导
- 架构模式
- 表达了软件系统的基本结构组织模式
- 重要部分是关注问题和上下文,以及如何应用上下文解决问题
- 架构模式:{问题,上下文} —> 架构方法
- 架构视图
- 是系统中特定类型的元素及其关系的表示
- 视将系统的实体划分为有趣且易于管理的系统表示
- 不同的视图支持不同的目标和用户,突出不同的系统元素和关系,同时在不同程度上暴露了不同的质量属性
连线,为每个风格列出4个视图 【2015】【2017】【2018】【2019】
- 它如何被构造成⼀组实现单元? Module styles
- 分解视图、使用视图、泛化视图、分层视图、领域视图、数据模型视图
- 它如何被构造成⼀组有运行时行为和交互的元素?Component-connector styles
- 管道-过滤器视图、客户机-服务端视图、点对点视图、面向服务架构视图、发布-订阅视图、共享数据视图、多层视图
- 它如何与它环境中的非软件结构关联?Allocation styles
- 部署视图、安装视图、工作安排视图、其他分配视图
为什么软件系统架构需要使用不同视图来文档化?给出4种示例视图的名称和目的。【2022】【2018】【2015】****【2022】
视图是⼀组系统元素及其关系的表示,这些元素不⼀定是全部系统元素,而是特定类型的元素。视图让我们将系统实体划分成感兴趣和易于管理的系统表示。
- 不同的视图支持不同的目标和用户,突出不同系统元素和关系。
- 不同视图在不同程度上展现不同的质量属性
- Module view:一组连续的实现单元
- C&C view:运行时行为和交互
- Allocation view:软件系统到非软件结构部分(开发环境、执行环境等)的映射
- Quality view:描述质量属性
- 组合视图:上述的组合。(我记得后面说可以识别边缘视图,然后将边缘视图和它关联的其他视图组合起来)
view包括哪5个部分:
- 主要展示
- 元素目录
- 上下文图
- 可变性指南
- 缘由
Structural views
module views
- 模块是提供一组连贯职责的实现单元,没有至少一个模块视图,任何软件架构的文档都不可能是完整的
- 分解视图 Decomposition view
- 使用视图 Uses view
- 泛化视图 Generalization view
- 分层视图 Layered view
- 领域视图 Aspects View
- 数据模型视图 Data model view
component-and-connector views
- 组件和连接器视图显示具有某些运行时存在的元素,例如进程、对象、客户端、服务器和数据存储(称为”组件”)
- 附件指示哪些连接器连接到哪些组件,通过将连接器的端点连接到组件的端口来显示附件
- 管道和过滤器视图 Pipe-and-filter view
- 客户端-服务器视图 Client-server view
- 点对点视图 Peer-to-peer view
- 面向服务的架构 (SOA) 视图 Service-oriented architecture (SOA) view
- 发布订阅视图 Publish-subscribe view
- 共享数据视图 Shared-data view
- 多层视图 Multi-tier view
allocation views
- 描述了软件单元到软件开发或执行环境元素的映射
- 通常目标是将软件元素所需的属性与环境元素提供的属性进行比较,以确定分配是否成功
- 可以描绘静态或动态视图
- 部署视图 Deployment view
- 安装视图 Install view
- 工作分配视图 Work assignment view
- 其他分配视图 Other allocation views
Quality views
- 安全视图 Security view
- 性能视图 Performance view
- 可靠性视图 Reliability view
- 沟通视图 Communication View
- 异常(错误处理)视图 Exception view (error-handling) view
Documenting views: 3-step for choosing views
- 构建涉众/视图表
- 合并视图
- 识別上表中的边缘视图
- 通过关联一个视图中的元素和另一个视图中的元素,将每个边缘视图与另一个具有更强选区的视图相结合
- 例如:不同的C&C视图之间;带有 SOA 或通信进程视图的部署视图之间;分解视图和工作分配、实施、使用或分层视图之间
- 确定优先级和阶段
- 分解视图
- 80/20原则
- 按顺序完成所有视图
Info.beyond views
- 文档信息
- Roadmap (文档路线图说明文档中的信息以及在哪里可以找到它)
- 版本控制
- 架构信息(视图之间的映射)
- 系统概述
- 视图之间的映射
- 基本理论
- 索引表、术语表、缩图词列表
Documentation package = View + Beyond
把所有views和beyond放在一起打包
6.Evaluating Architecture
Architecture analysis & evaluation methods
Why to evaluate architecture?
- 大型项目经常延迟交付(设计失败)和超出预算(商业组件COTS不能按照预期运行)
- 项目后期需要大量的返工
- 团队成员没有考虑
- 缺少可以尽早发现问题的专家
- 有代价
- 架构评估有助于缓解这些问题
- 彻底评估商业组件的稳定性
- 在问题修复成本较高前识別问题
- 设计缺陷
- 没有考虑到的商业组件行为
- 商业组件对整体系统架构不匹配
- 通知管理层,以方便他们做出更好的决策
- 传播架构/设计最佳实践
- 提供更好的技术和项目信息给管理层
- 确定通过培训可以对常见问题领域产生广泛影响的领域
- 改善与商业组件供应商的互动
When to evaluate an architecture?
- 期望选择不合适的商业组件最小风险时、涉及收购方和供应商(有明显的警告)时
- 演化/升级时:评估变化的影响
- 设计时:新架构适合需求的早期”验证”
- 构建时:实际架构是否按预期构建、是否被很好的构建
- 总是尽早地进行评估,为什么?:
- 还有时间来修复
- 修复错误的决定的成本相对比较小
- 是最有效的质量保证和风险缓解技术之一
- 这被认为是一种良好的商业惯例
How to evaluate software architecture?
- 评估架构的系统方法需要一种有助于提出正确问题的方法:来发现风险、识别错误的架构决定和确保质量问题得到解决
- 评估软件架构方法:
- Software Architecture Analysis Method (SAAM)
- Architecture Level Modifiability Analysis (ALMA)
- Performance Assessment of Software Architecture (PASA)
- Architecture Trade-off Analysis Method (ATAM)
- 这些方法都是基于场景的方法,因为质量属性是使用场景定义的
- 场景被映射到架构组件上,以评估架构能力,以满足所需的质量属性
How can a method be helpful?
- 帮助涉众尽早问正确的问题
- 识别风险:可能对所需质量属性产生负面影响的架构决策
- 发现敏感点:特定质量属性对其敏感的架构决策
- 发现权衡:影响多个质量属性的架构决策
- 发现趋势:架构决策与系统属性预测之间的相关性
- 可以通过进一步分析、设计或原型制作来减轻风险
- 所做的权衡和支持它们的理由可以适当地记录下来以备将来参考
Analysis Methods for Evaluation
Evaluate Forms(participants)
评估者是可以发现最佳实践的专家,且拥有不同项目的广阔视野
设计过程中:
- 设计师评估:使用“生成-测试”方法
- 同行评估
- 审查者:确定许多质量属性方案来推动审查
- 架构师:介绍要评估的架构部分
- 设计人员:对于每个场景,遍历架构并解释如何满足场景
- 潜在的问题被捕获
架构设计完成后:外部人员进行评估
ATAM: Architecture Tradeoff Analysis Method
Phase 0: Partnership & preparation 准备和建立团队
- 参与者:评估团队领导和关键项目决策者
- 输入:架构设计文档
- 输出:评估计划
- Who? 涉众的初步名单
- When? Where? and How?
- 什么时候评估报告被送给谁?
- 评估报告中应该包含什么信息?
Phase 1: Evaluation-1
- 参与者:评估团队和项目决策者
- 评估步骤:step1-6
- 输出:
- 架构的简明介绍
- 业务目标(驱动因素)的说明
- 作为场景实现的特定质量属性要求的优先列表
- 效用树 utility tree
- 风险和无风险
- 敏感点和权衡点
Phase 2: Evaluation-2
- 参与者:评估团队,项目决策者和架构涉众
- 评估步骤:step(1), 7-9
- 输出:
- 涉众社区的优先场景列表
- 风险主题和业务驱动因素各自受到的威胁
Phase 3: Follow-up
- 参与者:评估团队和主要涉众(评估客户)
- 评估过程:评估团队制作一份书面最终报告,分发给主要涉众以供审核,审查结束后,将报告提交给委托评估的人。
- 输出:最终评估报告
Steps
Step1 介绍ATAM - Present the ATAM
评估负责人向集合的项目代表(”决策者”)简要介绍 ATAM,让他们了解评估的过程和输出
The evaluation leader presents the ATAM in brief to assembled project representatives (‘decision makers’) for their understanding of the process and outputs of the evaluation
Step2 介绍业务驱动因素 - Present the Business Driver
项目经理或系统的客户从业务角度呈现系统概览,描述
Project manager or system’s customer presents a system overview from a business perspective, describing:
- 它最重要的功能需求 its most important functional requirements
- 其技术、管理、经济或政治限制 its technical, managerial, economic, or political constraints
- 其商业目标和上下文 its business goals and context
- 其主要涉众 its major stakeholders
- 架构驱动因素(塑造架构的主要质量属性目标)the architectural drivers (major quality attribute goals that shape the architecture)
Step3 展示架构 - Present the architecture
首席架构师在适当的细节级别上进行了描述架构的演示: The lead architect makes a presentation describing the architecture at an appropriate level of detail:
- 技术限制,例如规定使用的操作系统、硬件或中间件 technical constraints such as an OS, hardware, or middleware prescribed for use
- 系统必须与之交互的其他系统 other systems with which the system must interact
- 用于满足质量属性要求的架构方法 architectural approaches used to meet quality attribute requirements
Step4 确定架构方法 - Identify Architectural Approaches
- ATAM 专注于通过理解架构方法来分析架构。ATAM focuses on analyzing an architecture by understanding its architectural approaches.
- 在这一步,评估团队:By this step, the evaluation team
- 研究了架构文档 have studied the architecture documentation
- 听取了架构师的展示 have heard the architect’s presentation
- 向架构师询问了设计系统时使用的模式和策略 have asked the architect about patterns and tactics used in designing the system
- 评估团队对已确定的架构方法(风格、模式和策略)进行编目。The evaluation team catalogs the architectural approaches (styles, patterns and tactics) that have been identified.
Step5 生成质量属性效用树 - Generate Quality Attribute Utility Tree
- 这是指导其余分析的关键步骤。 This is a crucial step that guides the remainder of the analysis.
- 评估团队与项目决策者合作,确定、确定和优化系统最重要的质量属性目标。The evaluation team works with the project decision makers to identify, prioritize and refine the system’s most important quality attribute goals.
- 质量属性目标通过质量属性效用树详细阐述,该树通过精确定义相关质量属性需求使需求具体化。The quality attribute goals are articulated in detail via quality attribute utility tree that makes the requirements concrete by defining precisely the relevant quality attribute requirements.
Step6 分析架构方法 - Analyze Architectural Approaches
- 目标是让评估团队确信该方法的实例化适合满足特定于属性的要求。The goal is for the evaluation team to be convinced that the instantiation of the approach is appropriate for meeting the attribute-specific requirements.
- 评估团队通过要求架构师解释架构如何相互支持,一次检查排名最高的场景(来自效用树)。The evaluation team examines that the highest-ranked scenarios(from the utility tree) one at a time by asking the architect to explain how the architecture supports each other.
- 评估团队记录相关的架构决策,并通过讨论识别和分类其风险、非风险、敏感点和权衡。The evaluation team documents the relevant architectural decisions and identifies and catalogs their risks, nonrisks, sensitivity points, and tradeoffs through a discussion.
- 分析是为了引出足够的架构信息,以在已经做出的架构决策和需要满足的质量属性之间建立某种联系。The analysis is to elicit sufficient architectural information to establish some link between the architectural decisions that have been made and quality attributes that need to be satisfied.
- 在这一步结束时,评估团队应该清楚地了解整个架构的最重要方面、关键设计决策的基本原理以及风险、非风险、敏感点和权衡点的列表。At the end of this step, the evaluation team should have a clear picture of the most important aspects of the entire architecture, the rationale for key design decisions, and a list of risks, nonrisks, sensitivity points, and tradeoff points.
(Step-1) 展示ATAM和之前的结果: Present the ATAM & Previous Results
- 重复步骤 1,以便涉众了解方法和他们将扮演的角色。 Step 1 is repeated so that the stakeholders understand the method and the roles they are to play.
- 评估负责人总结第 2 步到第 6 步的结果,并分享输出(效用树除外)。The evaluation leader recaps the results of steps 2 through 6, and shares the outputs (except the utility tree).
Step-7 头脑风暴并确定场景的优先级: Brainstorm & Prioritize Scenarios
- 此步骤的目的是把握更大的涉众社区的脉搏,以了解系统成功对他们意味着什么。The purpose of this step is to take the pulse of the larger stakeholder community to understand what system success means to them.
- 评估团队要求涉众集思广益,就其个人角色而言,在操作上有意义的场景。The evaluation team asks the stakeholders to brainstorm scenarios that are operationally meaningful with respect to their individual roles.
- 一旦收集了场景,就会要求涉众对他们认为代表行为或质量问题的场景进行优先级排序和合并。Once the scenarios have been collected, stakeholders are asked to prioritize and merge scenarios they feel represent the behavior or quality concern.
- 将优先场景列表与效用树中的场景进行比较。The list of prioritized scenarios is compared with those from the utility tree.
- 如果差异很大,则额外的情景可能被识别为风险。If the discrepancy is significant, the additional scenario may be identified as a risk.
Step-8 分析架构方法 : Analyze Architectual Approaches
- 在此步骤中,评估团队执行与步骤 6 中相同的活动,使用排名最高的(例如前 5 到 10)但新生成的场景。In this step, the evaluation team performs the same activities as in Step 6, using the highest ranked (e.g. top 5 to 10), but newly generated scenarios.
- 架构师解释了相关的架构决策如何有助于实现每个决策。The architect explains how relevant architectural decisions contribute to realizing each one.
Step-9 展示结果: Present Results
- 评估团队根据共同的潜在问题或系统性缺陷将风险分组为风险主题。The evaluation team groups the risks into risk themes, based on common underlying concern or systemic deficiency.
- 然后,确定的风险主题与步骤 2 中列出的特定业务驱动因素相关。The identified risk themes are then related to specific business drivers listed in Step 2.
- 从评估中收集的信息被总结并呈现给所有涉众:The collected information from evaluation is summarized and presented to all stakeholders:
- 记录的架构方法 The architectural approaches documented
- 集思广益的场景集及其优先级 The set of scenarios and their prioritization from brainstorming
- 实用树 The utility tree
- 发现的风险和记录的非风险 The risks discovered and nonrisks documented
- 发现的敏感因素和权衡因素 The sensitivity points and tradeoff points found
- 风险主题和受威胁的业务驱动因素 Risk themes and the business drivers threatened by each one
- ATAM 第 1 天的示例议程 Example Agenda for Day 1 for ATAM
总结
Summary of ATAM phases
Summary of ATAM Outputs
- 阶段-0:准备和建立团队(输入是架构设计文档)
- 评估计划
- 阶段-1:评估-1
- 架构的简明介绍
- 业务目标(驱动因素)的阐释
- 作为场景实现的特定质量属性要求的优先级列表
- Utility Tree 效用树
- 风险和无风险点
- 敏感和权衡点
- 阶段-2:评估-2
- 涉众们的优先级场景列表
- 风险主题和业务驱动因素各自受到的威胁
- 阶段-3:后续
- 最终的评估报告
- 架构的简明展示
- 业务目标的阐述
- 表示为质量属性场景的优先质量属性要求
- 质量属性效用树
- 风险和非风险组
- 风险主题组
- 将架构决策映射到质量要求
- 敏感度和权衡点组
- 最终的评估报告
Lightweight Architecture Evaluation
详细设计
基础知识
依赖、关联、聚合、组合、泛化
认识 UML 类关系——依赖、关联、聚合、组合、泛化_依赖关系-CSDN博客
7大设计原则:单一职责原则、开闭原则、里氏替换原则、依赖倒转原则、接口隔离原则、合成复用原则、迪米特法则
目标:开闭原则
指导:最小知识原则
基础:单一职责原则
实现:依赖倒转、合成服用、里氏替换、接口隔离
思考题:在 JDK 中,java.util.Stack 是 java.util.Vector 类的子类,该设计合理吗?若不合理,请分析解释该设计存在的问题。
答:违反 LSP(里式代换原则)和合成复用
【2021】依赖倒转原则是什么?如何反映在设计模式中?
依赖倒转原则:高层模块不应该依赖于低层模块,而都应该依赖于抽象。抽象不应该依赖于具体,具体应该依赖于抽象。
反映:
- 策略
- 工厂方法、抽象工厂
- 模板方法
【2022】Please explain the Liskov Substitution Principle and how it contributes to the Open closed Principle.
所有引用父类的地方必须能透明引用子类的对象
里式替换是是实现开闭原则的重要方式之一,因为开闭原则的关键步骤就是实现抽象化,而基类与子类的继承关系就是抽象化的具体实现。所以里氏代换原则是对实现抽象化的具体步骤的规范。
设计模式
需要知道定义、使用环境、优缺点、符合的设计原则、uml、代码
策略模式 策略模式 | 菜鸟教程
- 许多相关的类仅在行为上有所不同,策略提供了一种使用多种行为之一配置类的方法
- 您需要算法的不同变体。例如,您可能定义了反映不同空间/时间权衡的算法。将这些变体实现为算法的类层次结构时,可以使用策略。
- 一种算法使用客户端不应该知道的数据。使用策略模式可避免暴露复杂的、特定于算法的数据结构
- 一个类定义了许多行为,这些行为在其操作中显示为多个条件语句。代替许多条件,将相关的条件分支移到他们自己的策略类中。
很多问题都出现于数据结构被暴露:比如迭代器模式。
开闭、依赖倒转
状态模式 状态模式(State)-CSDN博客
在很多情况下,一个对象的行为取决于一个或多个动态变化的属性,这样的属性叫做状态,这样的对象叫做有状态的(stateful)对象,这样的对象状态是从事先定义好的一系列值中取出的。当一个这样的对象与外部事件产生互动时,其内部状态就会改变,从而使得系统的行为也随之发生变化。
状态模式(State Pattern):允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象(Objects for States),状态模式是一种对象行为型模式。
在状态模式结构中需要理解环境类与抽象状态类的作用:
- 环境类实际上就是拥有状态的对象,环境类有时候可以充当状态管理器(State Manager)的角色,可以在环境类中对状态进行切换操作。
- 抽象状态类可以是抽象类,也可以是接口,不同状态类就是继承这个父类的不同子类,状态类的产生是由于环境类存在多个状态,同时还满足两个条件:这些状态经常需要切换,在不同的状态下对象的行为不同。因此可以将不同对象下的行为单独提取出来封装在具体的状态类中,使得环境类对象在其内部状态改变时可以改变它的行为,对象看起来似乎修改了它的类,而实际上是由于切换到不同的具体状态类实现的。由于环境类可以设置为任一具体状态类,因此它针对抽象状态类进行编程,在程序运行时可以将任一具体状态类的对象设置到环境类中,从而使得环境类可以改变内部状态,并且改变行为。
状态模式对“开闭原则”的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。
简单状态模式VS可切换状态模式
观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。
观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。
在以下情况下可以使用观察者模式:
- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
- 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
- 一个对象必须通知其他对象,而并不知道这些对象是谁。
- 需要在系统中创建一个触发链,A 对象的行为将影响 B 对象,B 对象的行为将影响 C 对象……,可以使用观察者模式创建一种链式触发机制。
例子:天气预报系统
背景: 一个天气预报系统中,天气数据(温度、湿度、气压等)变化时,需要通知多个显示设备(如手机应用、网页应用、LED显示屏等)更新显示。
1 | class WeatherData implements Subject { |
中介者模式(Mediator Pattern)定义:用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式,它是一种对象行为型模式。
系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解。
一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象。
想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。可以通过引入中介者类来实现,在中介者中定义对象交互的公共行为,如果需要改变行为则可以增加新的中介者类。
设计原则:迪米特法则!!!
命令模式(Command Pattern):将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式是一种对象行为型模式,其别名为动作(Action)模式或事务(Transaction)模式。
抽象方法:如果抽象类中包含抽象方法(没有具体实现的方法),那么继承这个抽象类的子类必须实现这些抽象方法。抽象方法以 abstract
关键字声明,并且没有方法体。
非抽象方法:对于非抽象方法(即有具体实现的方法),子类可以选择重写(Override)这些方法,也可以选择不重写,直接使用父类中的方法实现。
符合哪些设计原则?不会
【2021】组合命令(宏命令)
模板方法模式(Template Method Pattern):定义一个操作中算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。模板方法是一种类行为型模式。
相关内容:
模板方法模式鼓励我们恰当使用继承,此模式可以用来改写一些拥有相同功能的相关类,将可复用的一般性的行为代码移到父类里面,而将特殊化的行为代码移到子类里面。这也进一步说明,虽然继承复用存在一些问题,但是在某些情况下还是可以给开发人员带来方便,模板方法模式就是体现继承优势的模式之一。
在模板方法模式中,子类不显式调用父类的方法,而是通过覆盖父类的方法来实现某些具体的业务逻辑,父类控制对子类的调用,这种机制被称为好莱坞原则(Hollywood Principle),好莱坞原则的定义为:“不要给我们打电话,我们会给你打电话(Don‘t call us, we’ll call you)”。
钩子方法:最简单的钩子方法就是空方法,也可以在钩子方法中定义一个默认的实现,如果子类不覆盖钩子方法,则执行父类的默认实现代码。
在抽象类中定义一系列基本操作,这些基本操作可以是具体的,也可以是抽象的,同时,在抽象类中实现了一个模板方法,用于定义一个算法的骨架
外观模式(Facade Pattern):外部与一个子系统的通信必须通过一个统一的外观对象进行,为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。外观模式又称为门面模式,它是一种对象结构型模式。
符合:单一职责原则/迪米特法则
违背:开闭原则
模式适用环境:
在以下情况下可以使用外观模式:
当要为一个复杂子系统提供一个简单接口时可以使用外观模式。该接口可以满足大多数用户的需求,而且用户也可以越过外观类直接访问子系统。
客户程序与多个子系统之间存在很大的依赖性。引入外观类将子系统与客户以及其他子系统解耦,可以提高子系统的独立性和可移植性。
在层次化结构中,可以使用外观模式定义系统中每一层的入口,层与层之间不直接产生联系,而通过外观类建立联系,降低层之间的耦合度。
装饰模式
装饰模式(Decorator Pattern):动态地给一个对象增加一些额外的职责(Responsibility),就增加对象功能来说,装饰模式比生成子类实现更为灵活。其别名也可以称为包装器(Wrapper),与适配器模式的别名相同,但它们适用于不同的场合。根据翻译的不同,装饰模式也有人称之为“油漆工模式”,它是一种对象结构型模式。
请看spricoder,太多了,重点理解递归
组合多个对象形成树形结构以表示“整体-部分”的结构层次。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性
适配器模式(Adapter Pattern):将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。
对象适配器模式中,依赖适配者;类适配器中,继承适配者类
在以下情况下可以使用适配器模式:
- 系统需要使用现有的类,而这些类的接口不符合系统的需要。
- 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
注意和装饰者模式的区别
原型模式是一种对象创建型模式,用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。原型模式允许一个对象再创建另外一个可定制的对象,无须知道任何创建的细节。
抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为 Kit 模式,属于对象创建型模式。
工厂方法
工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,它属于类创建型模式。
在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。
应用场景专题 应该每年必考一道
策略模式
- 许多相关的类仅在行为上有所不同,策略提供了一种使用多种行为之一配置类的方法
- 您需要算法的不同变体。例如,您可能定义了反映不同空间/时间权衡的算法。将这些变体实现为算法的类层次结构时,可以使用策略。
- 一种算法使用客户端不应该知道的数据。使用策略模式可避免暴露复杂的、特定于算法的数据结构
- 一个类定义了许多行为,这些行为在其操作中显示为多个条件语句。代替许多条件,将相关的条件分支移到他们自己的策略类中。
很多问题都出现于数据结构被暴露:比如迭代器模式。
状态模式
- 对象的行为依赖于它的状态(属性)并且可以根据它的状态改变而改变它的相关行为。
- 代码中包含大量与对象状态有关的条件语句,这些条件语句的出现,会导致代码的可维护性和灵活性变差,不能方便地增加和删除状态,使客户类与类库之间的耦合增强。在这些条件语句中包含了对象的行为,而且这些条件对应于对象的各种状态。
观察者模式
- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
- 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
- 一个对象必须通知其他对象,而并不知道这些对象是谁。
- 需要在系统中创建一个触发链,A 对象的行为将影响 B 对象,B 对象的行为将影响 C 对象……,可以使用观察者模式创建一种链式触发机制。
中介者模式
- 系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解。
- 一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象。
- 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。可以通过引入中介者类来实现,在中介者中定义对象交互的公共行为,如果需要改变行为则可以增加新的中介者类。
命令模式
- 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
- 系统需要在不同的时间指定请求、将请求排队和执行请求。
- 系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。
- 系统需要将一组操作组合在一起,即支持宏命令。
模板方法
- 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
- 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。
- 对一些复杂的算法进行分割,将其算法中固定不变的部分设计为模板方法和父类具体方法,而一些可以改变的细节由其子类来实现。
- 控制子类的扩展。
外观模式
- 当要为一个复杂子系统提供一个简单接口时可以使用外观模式。该接口可以满足大多数用户的需求,而且用户也可以越过外观类直接访问子系统。
- 客户程序与多个子系统之间存在很大的依赖性。引入外观类将子系统与客户以及其他子系统解耦,可以提高子系统的独立性和可移植性。
- 在层次化结构中,可以使用外观模式定义系统中每一层的入口,层与层之间不直接产生联系,而通过外观类建立联系,降低层之间的耦合度。
装饰模式
- 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
- 需要动态地给一个对象增加功能,这些功能也可以动态地被撤销。
- 当不能采用继承的方式对系统进行扩充或者采用继承不利于系统扩展和维护时。不能采用继承的情况主要有两类:第一类是系统中存在大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长;第二类是因为类定义不能继承(如 final 类)。
组合模式
- 需要表示一个对象整体或部分层次,在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,可以一致地对待它们。
- 让客户能够忽略不同对象层次的变化,客户端可以针对抽象构件编程,无须关心对象层次结构的细节。
- 对象的结构是动态的并且复杂程度不一样,但客户需要一致地处理它们。
适配器模式
- 系统需要使用现有的类,而这些类的接口不符合系统的需要。
- 想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
原型模式
- 创建新对象成本较大,新的对象可以通过原型模式对已有对象进行复制来获得,如果是相似对象,则可以对其属性稍作修改。
- 如果系统要保存对象的状态,而对象的状态变化很小,或者对象本身占内存不大的时候,也可以使用原型模式配合备忘录模式来应用。相反,如果对象的状态变化很大,或者对象占用的内存很大,那么采用状态模式会比原型模式更好。
- 需要避免使用分层次的工厂类来创建分层次的对象,并且类的实例对象只有一个或很少的几个组合状态,通过复制原型对象得到新实例可能比使用构造函数创建一个新实例更加方便。
抽象工厂
- 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是重要的。
- 系统中有多于一个的产品族,而每次只使用其中某一产品族。
- 属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。
- 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。
工厂方法
- 一个类不知道它所需要的对象的类:在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类。
- 一个类通过其子类来指定创建哪个对象:在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
- 将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。
- 希望能够推迟创建的时候
微服务架构
1. 基础知识
定义:微服务架构是把应用程序功能性分解为一组服务的架构风格,每一个服务都是由一组专注、内聚的功能职责组成。
六大主要特性:
- 通过服务组件化
- 内聚和解耦
- 围绕业务能力组织
- 去中心化
- 基础设施自动化
- 服务设计与演进
主要特性
- 通过服务组件化:
组件: 可以独立替换和升级的软件单元
进程内组件
- 类、对象或库的形式
- 一般直接调用、以内存方式进行功能调用(共享内存)
进程外组件
- 微服务架构中的独立服务
- 实现组件化的方式是分解成服务
- 通过Web服务请求或 RPC机制通信
- 轻量级消息传递机制(如RabbitMQ)
- 产生明确的组件发布接口,封装(区别于文档)
- 耦合度低,隔离性好、独立开发、部署
- 远程调用性能损耗、合适的API粒度
- 围绕业务能力组织:
传统软件系统开发管理通常聚焦在技术层面
- UI团队、服务逻辑团队、数据库团队…
- 跨团队的沟通、交接和预算审批等
采用围绕业务能力的划分方法
- 服务业务领域内的宽栈实现
- 团队跨职能、全方位开发技能
- 如用户体验、数据库、项目管理……
采用产品开发模式
- 传统:项目模式,开发-维护,开发完解散
- 开发团队负责软件的整个产品周期
- 持续关注软件如何帮助用户提升业务能力,实现价值交付
- 内聚和解耦:
内聚: 单一职责,有各自的领域逻辑
解耦: 微服务间尽量减少直接依赖,独立自治。确定服务边界,使每个微服务负责独立的业务能力。业务功能分解;领域驱动设计
- 去中心化:
去中心化治理
- 构建微服务时可以有服务自己的技术栈选择
- 服务之间只需约定接口,无需关注内部实现
- 运维只需了解服务部署规范
去中心化数据存储
- 让每个微服务管理自己的数据库
- 或同一数据库技术的不同实例
- 或完全不同的数据库系统
去中心化数据管理
- 传统架构采用事务保证数据一致性,分布式微服务架构中数据管理困难
- 强调服务间的无事务协作,最终一致性和补偿策略
- 需权衡更大一致性的业务损失与修复错误的代价
- 基础设施自动化:
依赖自动化的基础设施、降低了开发和运维微服务的操作复杂度。
持续部署和交付: 编码、管理代码库、集成(构建、测试、打包)、部署、监控和运维
测试: 单元测试、集成测试、组件化测试、契约测试和端到端测试等
- 服务设计与演进:
高可用设计
- 容忍服务失败,客户端须尽可能有效地做出响应
- 完善的监控和日志记录,架构元素或业务指标、链路追踪
- 快速发现不良突发行为并尽早修复
演进式设计
- 传统架构软件变更难以预测且改造成本高昂
- 合理设计实现频繁、快速且控制良好的增量变更和演化
- 合适的服务解耦,只需重新部署修改的服务
- 变更频率不同,拆分(相同,合并)
- 架构适应度函数(Architectural fitness function)
2.核心设计模式
2.1 微服务的拆分和定义
关键步骤:
- 定义系统操作
- 定义微服务
- 根据业务能力进行服务拆分
- 根据子域进行服务拆分(通过领域驱动设计,类似于划分边界)
- 根据动静态调用关系进行服务拆分
- 定义API和协作方式:将系统操作映射到服务,确定在处理每一个系统操作时,服务之间如何交互
需求:
- 基本原则:高内聚低耦合
- 单一职责
- 共同封闭:变更频率相同的,放在同一个服务里面
- 双披萨团队开发:微服务数量不要太多,否则资源不够
- 团队自治:独立和自我治理
2.2 进程间通信机制复杂性
进程间通信机制复杂性高于方法调用、局部故障
问题1:同步通信中避免故障蔓延到其他服务?
上下文:
- 微服务,分布式,进程间调用
- 服务请求可能面临局部故障(故障/停机/过载)
- 同步通信客户端等待响应被阻塞,蔓延
需求:
- 处理网络超时/无响应服务的能力
- 限制客户端向服务器发出请求的数量
- 决定如何从失败的远程服务中恢复
模式:断路器。有闭合、断开、半断开状态,可以防止不断地尝试执行可能会失败的操作。
相关模式:API网关模式、服务器端服务发现模式
问题2:客户端如何在网络上发现服务实例的位置?
上下文:
- 不同微服务之间通常需要进程间调用
- 在传统的分布式系统部署下,服务在固定且已知的位置(主机与端口)运行,从而确保各服务可利用REST或RPC机制进行相互调用
- 微服务通常在虚拟化或者容器化环境中运行,服务实例数量和位置动态变化
需求:
- 每一服务实例的特定位置(主机与端口)信息
- 服务端实例的具体数量及位置动态变化信息
- 虚拟机与容器分配的动态IP地址信息
- 服务实例的数量信息的(EC自动伸缩组会根据负载情况随时调整实例数量)
模式:应用层服务发现模式
相关模式:替代模式:平台层服务发现模式
问题3:如何处理外部客户端与服务之间的通讯?
上下文:
- 多个版本客户端需要开发多个适配的用户界面
- 产品信息通过API访问
- 数据分布在多项服务之间
需求:
- 微服务通常提供的是细粒度API,客户端需要同多项服务进行交互
- 不同客户端需要不同的数据(桌面浏览器版本通常较复杂
- 不同客户端的网络性能亦有所区别(移动网络速度更慢)。服务器端Web应用能够向后端服务发送多条请求,不会影响用户体验,但移动客户端则只能发送少量请求
- 服务实例数量与其位置(主机与端口)会发生动态变化
- 服务的划分方式会随时间的推移而改变,且不应被客户端所感知
模式:API Gateway模式/后端前置模式
相关模式:后续模式:断路器模式、服务发现模式/API Gateway模式
2.3 部署复杂性
技术异构、相互隔离、经济高效
上下文
- 微服务架构包含一组服务
- 每个服务都部署为一组服务实例,以实现吞吐量和可用性
问题:如何部署以解决以下需求?
- 服务使用各种语言、框架和框架版本编写
- 需要快速构建、独立部署和扩展服务
- 服务实例需相互隔离
- 需限制服务消耗的资源(CPU 和内存)
- 尽可能经济高效地部署应用程序
模式列表:
• 资源需求冲突的风险
• 在主机(物理机或虚拟机)上运行不同服务的多个实例。
• 有多种方法可以在共享主机上部署服务实例,包括:
• 将每个服务实例部署为一个 JVM 进程。例如,每 个服务实例一个 Tomcat 或 Jetty 实例。
• 在同一个 JVM 中部署多个服务实例。例如,作为 Web 应用程序或 OSGI 包。
优点:
- 资源利用率相对较高
缺点:
- 资源需求冲突的风险
- 依赖版本冲突的风险
- 难以限制服务实例消耗的资源
- 在同一个进程中部署多个服务实例,很难监控每个服务实例的资源消耗,也不可能隔离每个实例
相关模式:
替代模式:单主机部署单个服务实例
在自己的主机上部署单个服务实例
优点:
- 服务实例彼此隔离
- 不存在资源需求或依赖版本冲突的可能性
- 一个服务实例最多只能消耗单个主机的资源
- 监控、管理和重新部署每个服务实例非常简单
缺点:
- 与单主机部署多个服务实例模式相比,资源利用效率可能较低,因为主机更多
相关模式:
替代模式:单主机部署多个服务实例、无服务器部署
特化模式:将服务部署到虚拟机、将服务部署到容器
将服务打包为虚拟机镜像,并将每个服务实例部署为单独的VM
优点:
- 通过增加实例数量来扩展服务很简单。Amazon Autoscaling
- Groups 可以根据负载自动执行此操作
- VM 封装了用于构建服务的技术细节,例如所有服务都以完全相同的方式启动和停止
- 每个服务实例都是隔离的
- VM 对服务实例消耗的 CPU 和内存施加限制
- AWS 等 IaaS 解决方案为部署和管理虚拟机提供了成熟且功能丰富的基础设施,如弹性负载均衡器、自动缩放组
缺点:
- 资源利用效率较低(整台虚拟机)
- 部署速度相对较慢(分钟级)
- 系统管理的额外开销(操作系统、运行补丁)
相关模式: • 替代模式:将服务部署到容器
• 泛化模式:单主机部署单个服务实例
将服务打包为 (Docker) 容器镜像并将每个服务实例部署到容器,容器是一种更现代、更轻量级的部署机制,操作系统级的虚拟化机制
部署过程: 构建Docker镜像、运行Docker镜像、构建容器镜像、推送到镜像仓库、运行Docker镜像
优点:
- 通过更改容器实例的数量可以直接扩展和缩减服务
- 容器封装了用于构建服务的技术细节,所有服务都以完全相同的方式启动和停止
- 每个服务实例都是隔离的
- 容器对服务实例消耗的 CPU 和内存施加限制
- 容器的构建和启动速度非常快
- 将应用程序打包为 Docker 容器比将其打包为 AMI 快 100 倍 Docker 容器启动速度明显快于 VM (仅启动应用程序进程而非整个操作系统)
缺点:
- 大量的容器镜像管理工作(操作系统补丁、基础设施)
- 部署容器的基础设施不如部署虚拟机的基础设施丰富
相关模式:
替代模式:将服务部署到虚拟机
泛化模式:单主机部署单个服务实例
使用公有云提供的serverless部署机制部署服务
部署细节对用户隐藏,用户和其组织不负责管理低级基础设施(无服务器概念)
(lss:了解一下就好)
第三方平台
lss:作业我们已经布置这些了,所以这部分内容几乎应该是可以确定是放到简答题里面,但是具体出哪几个考题这块到时候大家根据重点然后去看一下,推一下。
然后大概回顾一下吧。其实这两次课我们讲的内容很简单,就是你无非一个基础加一个模式,对吧?当然现在的模式大家听起来可能会比较枯燥一些,如果你有了开发实践经验,你会发现这块内容的讲解其实会有一些结合工程化的一些解决方案的。因为这里面会体现了大量的技术的解决方案、工具的解决方案,对吧?其实它也不是纯粹的我们的架构的这个层面的一个纯软件架构的这个层面的一个这个视角,对吧?其实我们有一点也竞价过这样的一个方案,那么定义我们不会去考,因为这个就太小儿科了。 但是你要理解它的一个定义加特性,包括我们为什么后边会有这么多的这个模式出来,包括你的这个拆分的定义的这个复杂,对吧?你外化的这些通信的复杂性、部署的复杂性和运维的复杂性,大家主要还是帮助大家有这个初步的了解之后,如果你感兴趣,需要去做深入的实践,才会有更深入的这个理解,好吧?嗯,具体的内容你去考,可能会出几个简答题,因为拆分定义我们已经做过作业了,所以不会让大家去设计。 那后续可能就是比如说通信的这个复杂性,我们讲的一些模式,大家部署的复杂性讲的这样的一些模式,包括关系大家会可以深入地去了解,运维因为我们没讲大家就了解一下就好了。
XX设计模式符合/不符合XX设计原则
模板方法 符合 单一指责、开闭原则
命令 符合
中介者
观察者
状态 不符合 开闭原则
策略