文章目录
- 系统分析与设计 复习
- 第 1 章 系统分析与设计概述
- 系统特性
- DevOps
- 第 2 章 系统规划
- **系统规划步骤**
- 规划模型
- 诺兰模型
- **CMM 模型**
- 系统规划方法
- 战略集合转换法 SST
- 关键成功因素法 CSF
- 企业资源规划法 BSP
- CSB 三者联系和区别
- 第 3 章系统分析
- 系统分析概述
- 业务流程图
- 系统流程图
- 第 4 章 系统设计
- 系统设计内容
- 系统设计原则
- 第 5 章 结构化设计
- 第 6 章 面向对象的设计
- 面向对象的设计概述与静态模型
- 面向对象的设计概述
- 静态模型
- 类图
- 对象图
- 接口
- 包图
- 动态模型:消息、顺序图、合作图
- 消息
- 顺序图
- 合作图
- 构件图和部署图
- 系统体系结构模型
- 构件图
- 部署图
- 设计模式
- 组成
- 设计原则
- 分类
- 创建型
- 单例模式:
- 原型模式:
- 工厂方法模式:
- 抽象工厂模式:
- 建造者模式:
- 结构型
- 代理模式(Proxy) :
- 适配器模式(Adapter)
- 桥接模式(Bridge)
- 组合模式(Composite)
- 装饰模式(Decorator)
- 外观模式(Facade)
- 享元模式(Flyweight)
- 行为型
- 模板方法模式:
- 策略模式:
- 命令模式(动作模式):
- 职责链模式:
- 状态模式:
- 观察者模式:
- 中介者模式:
- 迭代器模式:
- 访问者模式:
- 备忘录模式:
- 解释器模式:
- 第 7 章 安全设计
系统分析与设计 复习
没啥资料,随缘复习的,带偏勿怪。
思维导图部分节点太多 or 太细节收起来了,后期源文件会传到个人仓库。
第 1 章 系统分析与设计概述
系统特性
- 整体性:一般来说,系统的整体功能大于组成系统的各部分的功能之和
- 目的性:任何系统都有某种目的,都要实现一定的功能,多个目标可能不一致甚至矛盾,需要平衡求整体最优
- 相关性:各部分相互依赖、制约,某部分变化会影响其他部分
- 环境适应性:适应环境变化,保持原有功能
- 层次性:可以分解为一些列子系统,具有层次,各层次有独立的功能,通过相互联系、作用共同完成系统功能
系统分析:理解问题域
系统设计:求可行解
DevOps
开发运维一体化,人 + 流程 + 平台
五要素
- 文化:开发和运维结合
- 自动化:自动化一切可以自动化的
- 精益:小步快跑,持续改善
- 度量
- 分享
第 2 章 系统规划
系统规划步骤
- 对当前系统进行初步调查
- 分析确定系统目标
- 分析子系统组成和功能
- 拟定系统实施方案
- 进行可行性研究
规划模型
诺兰模型
- 初级阶段(计算机时代):初装,蔓延
- 中级阶段(信息资源规划时代):控制,集成
- 高级阶段(信息时代):数据管理,成熟
CMM 模型
- 三要素:能力、成熟度、模型
- 五个开发等级
- 初始级 Initial
- 可重复级 Repeatable
- 已定义级 Defined
- 已管理级 Managed
- 优化级 Optimizing
- 作用与目的
- 提高软件机构能力以满足成本、进度计划、功能及质量等目标
- 指导软件机构控制开发和维护软件的过程,并发展成为具有优秀软件工程和管理的机构文化
- 引导软件机构,在确定过程成熟度以及改进软件过程和软件质量遇到几个关键问题的过程中,选择过程改进策略
- 将工作重点集中在有限几个关键目标上,有效达到改进机构软件生产过程的效果,进而可持续改进软件生产能力
- 意义
- 对软件公司:提高软件公司软件开发的管理能力、软件生产率、软件质量、公司的国内和国际竞争力
- 对软件项目发包单位和软件用户:提供了对开发商管理水平的评估手段,有助于风险识别
系统规划方法
战略集合转换法 SST
MIS的战略规划过程是把组织的战略目标转化为管理信息系统战略目标的方法
步骤
- 识别组织的战略集
- 描绘出组织各类人员或实体结构
- 对于每类人员或实体识别系统相应的使命及战略
- 将组织战略集转化为信息系统战略
- 根据组织目标确定信息系统目标
- 对应组织战略集的元素识别相应信息系统战略的约束
- 根据信息系统目标和约束提出信息系统战略
关键成功因素法 CSF
通过分析找出使得企业成功的关键因素,然后再围绕这些关键因素来确定系统的需求,并进行规划
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p1DArkI2-1669205515066)(/home/zsl/.config/Typora/typora-user-images/image-20221123150510584.png)]
步骤:
- 了解企业或MIS的战略目标
- 识别所有的成功因素
- 确定关键成功因素
- 明确各关键成功因素的性能指标和评估标准
方法:头脑风暴法
表示方法:鱼骨图(因果图)
企业资源规划法 BSP
概念
- 为指导企业管理信息系统的开发而建立的规范方法。
- 用于企业内部系统开发。先自上而下识别系统目标、识别企业的过程、识别数据,然后再自下而上地设计系统目标,最后把企业目标转为信息系统规划的全过程。
- 根据企业目标制定出MIS战略规划的结构化方法
出发点
- 系统必要支持企业目标
- 系统战略应表达企业各个管理层要求
- 应向整个组织提供一致性信息
- 应在组织机构和管理机制改变时保持工作能力
- 系统战略规划应由总体系统中的子系统开始实现
自上而下的分析规划和自下而上的实施策略
最早面向过程管理的思想方法
核心步骤:定义企业目标→定义企业过程→定义数据类→定义信息系统总体结构
具体步骤
- 准备工作
- 调研,动员,定义目标
- 定义业务过程(企业过程或管理功能组)(核心)
企业活动一般由三个方面组成:
- 计划和控制(战略规划和管理控制)
- 产品和服务(需求、获取、服务、退出)
- 支持资源(资金、人事、材料、设备)
结果:过程组织矩阵
- 业务过程重组:在业务过程识别的基础下,明确
- 哪些业务过程是正确的
- 哪些业务过程低效,需要在信息技术支持下实现优化
- 哪些业务过程无效,或不适合于计算机处理,应当在业务中予以取消
- 定义数据类
- 数据:指支持业务过程所必需的逻辑相关的数据
- 目的:了解企业目前的数据状况和数据要求,以及数据与企业实体、业务过程之间的联系,查明数据共享的情况,建立功能/数据类矩阵,为定义信息系统总体结构提供基本依据。
- 方法:实体法、功能法
- 实体法
实体分类:指企业实施管理的对象,一般可按人、地点、物体、概念和事件进行分类,如企业员工、设备、产品和材料等。
- 计划型:反映目标的计划值
- 统计型:反映企业的综合状况
- 文档型:反映实体的现状
- 业务型:反映生命周期各阶段相关文档型数据的变化
绘制实体(资源)/数据类矩阵
- 功能法:输入-过程-输出图
6、定义信息系统总体结构
划分子系统。BSP方法将过程和数据类两者作为定义企业信息系统总体结构的基础,用过程/数据矩阵(也称U/C矩阵)表达两者之间的关系。
U/C 矩阵
- 过程/数据矩阵(U/C)行表示数据类,列表示过程,字母U(use)和C(create)来表示过程对数据类的使用和产生
- 主要功能
- 正确性校验:及时发现前段分析和调查工作的疏漏和错误,分析数据的正确性和完整性
- 对 U/C 求解过程得到子系统的划分
- 通过子系统之间的联系U 可以确定子系统间共享的数据
- 可能的问题
- 多功能生成同一数据类:功能合并或分解数据类
- 数据类无 C/U:对功能核对
- C/U 分布无规律:调顺序
- 正确性校验
- 完备性检验:每个数据类必须有一个产生者(C)和至少一个使用者(U),每个功能则必须有产生或使用(U或C)数据类型。
- 一致性检验:每个数据类型必有且仅有一个产生者(C)
- 无冗余性检验:指 U/C矩阵中不允许有空行和空列
- 7、确定总体结构中的优先顺序
- 8、完成BSP研究报告,提出建议书和开发计划
CSB 三者联系和区别
第 3 章系统分析
系统分析概述
系统分析:借助于当前系统的逻辑模型导出目标系统的逻辑模型,解决目标系统 “做什么” 的问题
目的:将需求及解决方法确定下来,建立逻辑模型
需求工程阶段
- 可行性分析
- 需求开发
- 需求获取
- 需求分析
- 需求规格说明
- 需求验证
- 需求管理
需求三层次
- 业务需求
- 用户需求
- 系统需求
需求分类
- 功能
- 非功能:性能、质量属性、接口、约束、可靠性、安全性、保密性
业务流程图
业务流程分析
- 业务功能分析:在调查研究的基础上,按照企业组织结构,详细列出企业功能
- 业务关系分析:流程中各活动间的逻辑联系、时序关系、数据联系、资源约束和活动的相关性等, 分析各个活动之间的关系等。
- 业务流程优化:按计算机信息处理的要求,分析哪些过程有冗余信息处理,哪些活动可以变串行处理为并行处理,变事后监督为事前或事中控制,产生更为合理的流程。
定义
- 用一些规定的符号及连线来表示某个具体业务处理过程。是一种系统分析人员都懂的共同语言, 用来描述系统组织结构、业务流程
- 绘制是按业务的实际处理步骤和过程进行的
- 注重业务职能的流程,业务的流转而非事务
可以用泳道划分
系统流程图
又叫事务流程图,反应主体框架。是在计算机事务处理应用进行系统分析时常用的一种描述方法,描述事务处理中从数据输入开始到获得输出为止各个处理工序过程描绘系统物理模型的工具。
基本思想是用图形符号以黑盒子的形式描绘系统理念的每个部件包括程序,文件,数据库,表格,人工过程等,表达信息在各个部件之间流动的情况,而不是表示对信息进行加工处理的控制过程
基本处理工序
- 变换:把输入单据变换成磁盘文件,或把磁盘文件变换成输出单据,或把某一磁盘文件的内容由一个介质文件传送到另一介质文件
- 合并:把多个文件合并为一个文件
- 划分:是合并的逆操作,将合并工序的输入文件与输出文件对调即可
- 分类(排序):按指定的键(关键字)以升序或降序改变原文件的记录排列顺序。例如,将如下记录排列的旧文件,按关键字升序,依次进行分类,得到新文件
- 更新:将多个文件作为输入根据关键项目进行对照,对文件进行内容修正、删除、增加等改写工作,一般更新的内容先要写入一个临时文件
第 4 章 系统设计
系统设计内容
- 功能
- 性能
- 过程设计(处理流程)
- 运行环境
- 用户界面设计
- 关键技术和算法
- 数据库,数据结构
- 安全性,保密性
- 为响应需求做出的其他系统级的设计决策
- 系统架构设计:总体,层次结构,部件,接口,动态交互
- 输入输出(I/O):对输入或条件进行响应的系统行为的设计决策
- 硬件
- 代码设计
- 系统配置项设计,人工处理等
- 运行设计
- 出错处理设计
- 系统维护设计
系统设计原则
- 组件化
- 抽象化
- 设计一个类时,不让该类面向具体的类,而是面向抽象类或接口,即所设计类中的重要数据是抽象类或接口声明的变量,而不是具体类声明的变量
- 在较低的抽象层次上,则采用过程化的方法
- 在最高的抽象层次上,可以使用问题所处环境的语言概括地描述问题的解法。
- 软件系统进行模块设计时,可有不同的抽象层次。
- 过程的抽象
- 数据的抽象
- 内聚和耦合
- 内聚
- 低内聚
- 偶然内聚:模块内各个操作之间基本无联系或只有很松散的联系
- 逻辑内聚:模块内各个操作功能类似,通过判断参数决定某功能的执行,又称控制内聚
- 时间内聚:模块内的操作基本无关联,仅因为执行时间相同而组合在一起
- 中内聚
- 过程内聚:模块内的操作必须按照特定顺序执行
- 通信内聚:模块内的操作有相同的输入或输出数据
- 高内聚
- 信息内聚(顺序):模块多种功能在同一个数据结构上操作,各功能有唯一入口点
- 功能内聚:模块内的操作是完成某一功能必不可少的部分
- 耦合
- 内容耦合(Content Coupling)
- 一个组件访问另一组件内部数据
- 一个组件不通过正常入口转到另一组件内部
- 两个组件有一部分程序代码重叠(只可能出现在汇编语言中);
- 一个组件有多个入口
- 公共耦合 Common Coupling
- 多个模块引用同一个全局数据区
- 两种情况:松散公共耦、紧密公共耦合
- 问题:公共部分的改动将影响所有调用它的模块;公共部分的数据存取无法控制;复杂程度随耦合模块的个数增加而增加
- 外部耦合 External Coupling:一组模块都访问同一全局简单变量而不是同一全局数据结构,且不是通过参数表传递该全局变量的信息,则称之为外部耦合
- 控制耦合Control Coupling
- 传递的信息中有控制信息(尽管有时这种控制信息以数据的形式出现) 。
- 它增加了系统的复杂程度。控制耦合常是多余的,在把模块适当分解后通常可用数据耦合代替
- 标记耦合,特征耦合(Stamp Coupling):一个数据结构的一部分借助于模块接口被传递
- 数据耦合(Data Coupling)低耦合
- 两模块彼此间通过简单数据参数交换信息,且交换的信息仅是数(不是控制参数、公共数据结构或外部变量)来交换输入、输出信息的
- 系统中至少必须存在这种耦合,因为只有当某些模块的输出数据作为另一些模块的输入数据时,系统才能完成有价值的功能。一般,一个系统内可以只包含数据耦合
- 非直接耦合(Nondirect Coupling)
- 两模块间没直接关系,它们间的联系完全是通过主模块的控制和调用来实现的
- 模块独立性最强
- 原则:实际上,模块之间是混合式的耦合;尽量使用数据耦合,少用控制耦合,限制公共耦合的范围,完全不用内容耦合。
- 封装与隐蔽
- 继承与复用(“白盒”复用)
- 优点:易于修改、扩展被复用的方法
- 缺点:无法在运行时改变从父类继承的方法的行为;子类和父类是强耦合关系;父类的内部细节对于子类而言是可见的
- 组合与复用(“黑盒”复用)
- 优点:使用委托机制、弱耦合关系、运行时动态制定所包含的对象
- 缺点:容易导致对象过多、必须仔细地设计接口
- 启发式规则
- 深度,宽度,扇出,扇入
- 作用域和控制域
- 可预测性
- 争取低耦合、高内聚(增加内聚 > 减少耦合
- 模块规模适中:过大不易理解;太小则接口开销过大。注意分解后不应降低模块的独立性
- 适当控制 :深度 = 分层的层数。过大表示分工过细。宽度 = 同一层上模块数的最大值。过大表示系统复杂度大
- 模块独立性
- 模块三个基本属性
- 功能:描述该模块实现什么功能
- 逻辑:描述模块内部怎么做
- 状态:该模块使用时的环境和条件
- 重要性
- 有效的模块化(即具有独立的模块)的软件较容易开发。因能分割功能且接口可简化,多人分工合作开发,该优点很重要
- 独立的模块较易测试和维护。因修改设计和程序需要的工作量较小,错误传播范围小,要扩充功能时能够“插入”模块
第 5 章 结构化设计
第 6 章 面向对象的设计
面向对象的设计概述与静态模型
面向对象的设计概述
静态模型
- 种类:类图、对象图、包图
- 步骤:
- 寻找确定对象类
- 定义类的接口
- 定义类之间的关系
- 建立对象类图
- 建立系统包图
类图
类之间的关系(4-6种)
- 关联(拥有, ASSOSATION,使用实例连接/单,双,自,弱)
- 关联和聚合的区别:语义上,关联的两个对象之间一般是平等的
- 关联和泛化(类之间的语义关系)
- 聚合 HAS A
- 整体和部分关系
- 比关联强,比组合弱
- 组合 contains-a
- 整体和部分关系,合成关系
- 部分不能离开整体,同生共死
- 整体的重数必须是0或1
- 泛化(继承, GENERALIZATION )
- 一般和特殊的区别
- 受限泛化(高级):多重、不相交、完全和不完全
- 实现:拥有,类和接口的关系
- 依赖(DEPENDENCY)
- 一个是独立的模型元素,另一个是依赖的,独立元素的变化会影响依赖的元素
- 暗示如果没有依赖类的支持会不完整
- 关联与类依赖
- 类关联强调结构关系,类依赖强调使用关系
- 依赖关系偶然、临时、弱的关系
- 关联可双向,依赖单向
- 类的成员变量形式出现则另一个类则为关联,局部变量形式出现则为依赖
类图结构
- 整体和部分has-a
- 聚合
- 组合
- 一般和特殊 is-a
- 分类关系
- 归纳关系
- 继承关系(泛化)
- 实例连接
- 简单的实例连接
- 二元关联的实施:一对一、一对多、多对多
- 复杂的的实例连接
- 三元关联
对象图
对象图
- 对象图中包含对象和链,对象是类的特定实例,链式类之间的关系的实例,表示对象之间的特定关系
- 对象图用来描述特定时刻各个对象之间的关系,是类图在某个特定时刻的实例
- 一个系统可以有多个对象图
- 对象图描述系统内某个时刻的静态结构
类图和对象图区别
- 分栏数量:类图三个分栏:名称、属性和操作;对象图两个分栏:名称和属性
- 名称:类的名称分类只有类名;对象名称分栏形式为”对象:类名";匿名对象名称形式为":类名"有下划线
- 操作:类中列出了操作;对象图不包含操作,因为对于属于同一个类的对象而言,其操作是相同的
- 连接:类使用关联连接,关联使用名称、角色、多重性以及约束等特征定义;类使用链连接,链有名称、角色,但没有多重性,对象代表是单独的实体,所有链都是一对一的,因此不涉及多重性
- 属性:类的属性分栏定义了所有属性的特征;对象则只定义了属性的当前值
接口
概念
- 接口是特殊的抽象类,没有属性(可以定义不能实现,要初始化,需要实现它的类来实现),只有操作(没有具体实现)
- 是描述类的部分行为的一组操作,只负责定义不负责实现
- 接口是在没有给出对象的实现和状态的情况下对对象行为的描述
接口的优势
- 不只可以作用于引用类型还可以用于值类型,抽象类只能用于引用类型
- 通过接口实现多继承
- 可以被多个类型重用
- 减少暴露的属性和方法,保护类型对象
接口的缺点:定义的方法,属性只能相对于继承它的类型。多层继承关系很难
和抽象类相似
- 不能实例化
- 包含未实现的方法声明
- 位于继承层次的上层
- 派生类必须实现未实现的方法,抽象类是抽象方法,接口是所有成员
和抽象类区别
- 概念
- 接口:一种行为规范,子类是“行为需要按照接口来完成”如“叫”;是抽象类的变体,特殊的抽象类
- 抽象类:事物的高度聚合,子类对于抽象类是“是”的关系;不’完全’的类,相当于是接口和具体类的一个中间层.即满足接口的抽象,也满足具体的实现对 对象的抽象
- 可定义的成员
- 接口:方法(但不实现)、属性(不包括字段),索引,事件(不包含委托)
- 抽象类:可有构造方法,成员变量(可以用不同的修饰符修饰)
- 不能包含的
- 接口:常数,字段,运算符,委托,内部类,析构函数,构造函数,静态成员(C#)JAVA:变量(除 public static final成员变量)
- 抽象类:不能出现抽象构造函数,抽象静态方法
- 抽象方法
- 接口全部、public 权限
- 抽象类部分。一个抽象类有一个或多个抽象方法
- 定义类型方法
- 接口不给
- 抽象类可以给出实现也可不给
- 具体属性
接口无具体属性
抽象类可以有具体属性 - 继承类对两者涉及方法的实现
- 接口:与子类相似,除了该实现类不能从接口定义中继承行为;要给出相应的方法和属性实现(都要重写)
- 抽象类:对抽象类定义的方法可以不重写(非抽象方法,或是子类也为抽象类);如果一个非抽象类是某个抽象类的子类,那么它必须重写父类的abstract方法,即在子类中将abstract方法重新声明,但必须去掉abstract修饰符。同时要保证声明的方法名字、返回类型、参数个数和接口中的方法完全相同
- 新增方法
- 接口:修改继承类,提供新定义方法(一旦公布不应改变
- 抽象类:继承类可不做任何处理(不会对子类影响)
- 其他
- 接口:一个类可以实现多个接口;在抽象类没有可供继承的默认实现时,一般用接口代替该抽象类;根本不知道类的存在;如果行为跨越不同的类,可用接口
- 抽象类:一个类只能继承一个直接的父类,这个父类可能是抽象类;定义一个类时不打算给他创建对象,只想作为基类,可将其声明为抽象类;子类—父类;对相似类的对象—使用继承类
包图
包:展现模块和模块之间的依赖关系
包拥有的元素:类、接口、组件、节点、协作、用例、图以及其他包
特点:一个模型元素不能被一个以上的包所拥有;如果一个包被撤销,其中元素也被撤销
一个包形成了一个命名空间,和其他的区分:简单名、路径名
可见性:private、protected、public
包的嵌套
包之间的关系:依赖、继承
动态模型:消息、顺序图、合作图
消息
三部分:发送者、接收者和活动
分类
- 两种系统
- 顺序系统:同步消息
- 并发系统:同步(阻断、限时),异步(无论是否准备好)
- 基本分类
- 简单消息
- 同步消息
- 异步消息
- 返回消息
- 接受者是否唯一
- 定向消息
- 广播消息
顺序图
概念
- 用来描述对象间的交互行为。表现用例中的行为顺序,描述了如何一步步完成系统的某项功能
- 注重消息的时间顺序,即对象间消息的发送和 接收的顺序,并将交互建模成对象之间消息交换的图形
- 顺序图还揭示了一个特定场景的交互,即系统执行期间发生在某个时间点的对象之间的特定交互,它适合于描述实时系统中的时间特性和时间约束
- 序列图将交互关系表示为一个二维图。其中,纵轴是时间轴,时间沿竖线向下延伸。横轴代表了在交互中各独立的对象
组成
- 对象:顺序图中所包含的每个对象用一个对象框(短式)表示,对象名需带下划线
- 生存线:对象框下画的一条垂直虚线,称为该对象的生存线,表示对象的生存时间
- 激活期:对象生存线上的一个细长方形框,表示该对象的激活时间段,即活动期间
- 消息:对象之间消息的发送和接收用两个对象生存线(激活期)之间的消息箭头线
分支控制
约束
循环控制
对象创建与消亡
合作图
概念
- 合作图可以用来描述系统对象之间的交互,表现对象协作关系的图,动态视图的另一种表现形式
- 强调这组对象之间的关系,强调发送和接受消息的对象之间的结构组织的交互图,显示对象、对象之间的链接以及对象之间的消息
- 它表示了协作中作为各种类元角色的对象所处的位置,在图中主要显示了类元角色(Classifier Roles)和关联角色(Association Roles)
组成
- 对象
- 链接:表示参与协作执行的关联的描述多重性、角色;当协作被实例化时,对象受限于类元角色,连接受限于关联角色;链是对象间的发送消息的路径
- 消息
- 嵌套消息:整数指定顺序号,如1.1是消息1的第一个嵌套消息
- 并发消息:并行的控制线程,如1. 2a和1. 2b
- 循环消息:*[循环执行条件]
- 条件发送消息:[执行条件]
- 异步消息
- 回调消息
- 约束
- 全局性:角色是全局的
- 局部性:角色是一个操作中的局部变量
- 参数性:角色是一个操作中的参数
- 自我性:对象可以向自身发送消息
- 表决性:用于通过约束(通过对回送值的表决)回送消息
- 广播性:一组消息的约束(系统中每个对象都是潜在的目标对象)
- 对象的创建与消亡
- 创建{new}
- 消亡{destroyed}
- 创建并消亡{transient}
构件图和部署图
系统体系结构模型
软件系统体系结构模型
概念:是系统的逻辑体系结构模型,刻画系统功能在逻辑组成部分上的分配,以及各部分间如何协调工作
作用
- 指出系统应该具有的功能;
- 为完成这些功能,涉及到哪些类,这些类之间如何相互联系;
- 类和它们的对象如何协作才能实现这些功能;
- 指明系统中各功能实现的先后时间顺序;
- 根据软件系统体系结构模型,制定出相应的开发进度计划。
通用的描述方法
- 通用接口界面层
- 系统业务对象层
- 系统数据库(持久对象和数据)层
硬件系统体系结构模型
- 概念:是系统的逻辑体系结构模型,刻画系统功能在逻辑组成部分上的分配,以及各部分间如何协调工作
- 作用
- 标明系统中配置的计算机和其他硬件设备;
- 并指明系统中各种计算机和硬件设备如何进行相互连接;
- 指出系统中的类和对象涉及的具体程序或进程;
- 这些程序和进程的执行依赖具体计算机;
- 明确不同的代码文件之间相互的依赖关系;
- 如果修改某个代码文件,标明哪些相关(与之有依赖关系)的代码文件需要重新进行编译
构件图
构件图:物理方面建模时要用的两种图之一,说明构件之间的逻辑关系
简单构件图案例(也可以嵌套)
构件
构件:逻辑体系结构中定义的概念和功能在物理体系结构中的实现
作用
- 对源代码建模
- 对可执行体的建模
- 从整体了解物理部件,显示构件间关系
- 可调整的系统建模
表示:组件,接口,关系(实现、依赖、关联、继承)
特点
(1)接口:描述一个构件能提供服务的操作,位于两个构件中间,割断了它们间的依赖关系,使构件具有良好的封装性。给定的接口,可以被1个构件输出,也可被另一构件输入。一个构件可以既输出接口又输入接口。
(2)操作:构件通过消息传递方式进行操作,每个操作由输入输出变量、前置条件和后置条件来决定。前置条件,后置条件
(3)实例化:构件是个物理实体,实例化代表运行期间的可执行软件模块(类是逻辑抽象,可有多个实例)。
(4)与配置环境的亲合性:构件从内、外两方面满足于配置环境的相容性:外部:利用配置环境提供的某组操作,降低构件的复杂程度。内部:构件提供一组其配置环境需要的操作,达到亲合的目的。
(5)能与同环境下其它构件进行交互。能够调用其他构件也可以被其他构件使用。
(6)构件可以是可执行代码、二进制代码和源代码形式
(7)可替换的物理实体。构件是物理实体而不是逻辑概念,具有可替换性。
(8)系统的组成部分。很少独立存在,可多个系统中复用。
(9)构件是软件复用的基本单元。
与类的相同点
- 都有名称
- 都可实现一组接口
- 都可参与依赖、继承、关联等关系和交互
- 都可被嵌套
- 都可有实例
与类的不同点
- 抽象方式不同
- 抽象级别不同
- 访问方式不同
- 与包的关系
构件的组织
- 用包来组织构件
- 用构件之间的交互关系来组织构件(依赖、继承、关联、实现)
构建的分类
- 源代码构件:<>、<>、<>
- 二进制构件:<>
- 可执行构件:<>、<>
接口:接口描述一个构件能提供服务的操作,是一个有操作而无实现的类
- 输出接口:构件实现接口,即构件被使用的接口。一个构件可以有多个输入接口。
- 输入接口:构件使用的接口,即使用其它构件的接口。构件必须遵从该接口并以此为基础来构造构件。一个构件可遵从多个输入接口。
- 一个构件可以既有输出接口有输入接口
部署图
部署(配置)图:描述处理器、设备和软件构件运行时的体系结构
基本元素:结点、组件、对象、连接、依赖
应用范围:网络环境下的分布式、嵌入式系统
每一个模型中仅包含一个部署图结点之间的通信关联:连接硬件时通常关心节点之间是如何连接的(如以太网、并行、TCP或USB等)。
依赖
- 支持依赖:一个结点和其内部构件
- 成为依赖:不同结点内部构件或对象之间
设计模式
组成
- 名
- 问题
- 解决方案
- 效果
设计原则
- 单一职责原则(SRP,Single-Responsibility Principle)
- 一个设计元素只做一件事,不要让类多功能化
- 如果应用程序影响到类中某一种职责,应将他与其他职责分开。即分离类的职责,不要让一个类承担过多职责,避免设计脆弱
- 接口:接口程序有两个职责:调制解调器的连接处理,两个函数的数据通信
- 开闭原则(OCP,The Open-Closed Principle)
- 一个软件实体如类,模块和函数应该对扩展开放,对修改关闭。
- 软件实体应该对扩展开放,对修改关闭,其含义是说一个软件实体应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化
- 利用抽象机制:基类和子类是封闭的,不可修改;可以派生新类实现新需求可扩展
- 里氏替换原则(LSP,Liskov-Substitution Principle)
- 子类型必须能够替换掉它们的基类型。
- 是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化
- 依赖倒置原则(DIP,Dependency-Inversion Principles)
- 改掉过程化的高层依赖底层,变成细节依赖抽象。即针对接口编程,不针对实现编程。使用接口和抽象类对返回值和变量说明
- 设计时,尽量从抽象类继承,而不是从具体类继承。继承等级树的所有叶子节点应当是具体类,而所有的树枝节点应当是抽象类或者接口。可减少类间的耦合,提高系统的稳定性,减少并行开发引起的风险,提高代码的可读性和可维护性。大型项目中体现明显。规避非技术性因素引起的问题。以轻松扩展
- 是几个设计原则中最难实现的。是实现开闭原则的重要途径
- 接口隔离原则(ISP, see Interface Segregation Principles)
- 尽量提供 小 接口。简单设计会过大。因为每个客户程序并不依赖于接口里的很多
- 优先使用组合而不是继承原则(CARP)
- 在许多设计中,人们希望系统的类之间尽量是低耦合的关系,而不希望是强耦合关系。即在许多情况下需要避开继承的缺点,而需要组合的优点。
- 迪米特原则(LOD)
- 知识最少原则,不要和陌生人说话。熟人好办事
- 即 一个对象应该对其他对象有尽可能少的了解。即 两个类不必彼此直接通信。通过第三者调用对方的方法。
分类
按目的分
- 创建型模式:主要用于创建对象
- 结构型模式:主要用于类或对象的组合
- 行为型模式:主要用于描述对类或对象怎样交互和怎样分配职责
按范围分
- 类模式:处理类和子类之间的关系,这些关系通过继承建立,在编译时刻就被确定下来,是属于静态的
- 工厂方法模式
- (类)适配器模式
- 解释器模式
- 模板方法模式
- 对象模式:处理对象间的关系,这些关系在运行时刻变化,更具动态性
创建型
创建型模式的主要关注点是“怎样创建对象?”
主要特点:是“将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节,对象的创建由相关的工厂来完成。就像我们去商场购买商品时,不需要知道商品是怎么生产出来一样,因为它们由专门的厂商生产。
单例模式:
某个类只能生成一个实例,该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。
结构与实现
- 要点
- 构造函数设为私有,外部类无法 new 构造函数
- 定义一个静态私有实例,并向外提供一个静态的公有函数用于创建或获取该静态私有实例
- 实现形式
- 懒汉式单例
- 该模式的特点是类加载时没有生成单例,只有当第一次调用 getlnstance 方法时才去创建这个单例。
- 如果编写的是多线程程序,则不要删除上例代码中的关键字 volatile 和 synchronized,否则将存在线程非安全的问题。如果不删除这两个关键字就能保证线程安全,但是每次访问时都要同步,会影响性能,且消耗更多的资源,这是懒汉式单例的缺点。
- 饿汉式单例
- 该模式的特点是类一旦加载就创建一个单例,保证在调用 getInstance 方法之前单例已经存在了
- 饿汉式单例在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以是线程安全的,可以直接用于多线程而不会出现问题
- 角色
- 单例类:包含一个实例且能自行创建这个实例的类。
- 访问类:使用单例的类
优点
- 提供了对唯一实例的受控访问。
- 可以节约系统资源,提高系统的性能。
- 允许可变数目的实例。可基于单例模式进行扩展,使用与单例控制相似的方法来获得指定个数的对象实例
缺点
- 没有抽象层,因此单例类的扩展有很大困难。
- 违背了“单一职责原则”。因为单例类既充当了工厂角色,提供了工厂方法,同时又充当了产品角色,包含一些业务方法,将产品的创建和产品的本身的功能融合到一起
- 滥用单例将带来负面问题,如为节省资源将数据库连接池对象设计为单例类,可会导致共享连接池对象的程序过多而出现连接池溢出;很多面向对象语言的运行环境都提供自动垃圾回收技术,因此,如实例化的对象长时间不被用,系统会认为是垃圾,会自动销毁并回收资源,下次利用时又将重新实例化,这将导致对象状态的丢失。
原型模式:
将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。
工厂方法模式:
定义一个用于创建产品的接口,由子类决定生产什么产品。(推迟到具体子工厂类中)
优点
- 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
- 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;
缺点
- 每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度
- 增加新产品时会违背“开闭原则”
角色
- 抽象工厂:提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品。
- 具体工厂:主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
- 抽象产品:定义了产品的规范,描述了产品的主要特性和功能。
- 具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。
适用
- 客户只知道创建产品的工厂名,而不知道具体的产品名。如 TCL 电视工厂、海信电视工厂等。
- 创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。
- 客户不关心创建产品的细节,只关心产品的品牌。
抽象工厂模式:
概念
- 提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。
- 是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构
- 抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。
产品族:指位于不同产品等级结构(电冰箱,电视机)中,功能相关联的产品组成的家族。一般是位于不同的等级结构中的相同位置上。每个产品族中含有产品的数目,与产品等级结构的数目是相等的,形成一个二维的坐标系,水平坐标是产品等级结构,纵坐标是产品族。叫做相图
组成:由抽象工厂、具体工厂、抽象产品和具体产品等 4 个要素构成,但抽象工厂中方法个数不同,抽象产品的个数也不同
适用
- 当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等。
- 系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。
- 系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。
优点
- 隔离了具体类的生产,使得客户并不需要知道什么被创建。
- 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象
- 增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则
缺点
- 增加新的产品等级结构很复杂,需要修改抽象工厂和所有的具体工厂类
- 如果要增加一个产品结构,改动大。抽象类要增加一个方法,然后,两个实现类都要改,严重违反开闭原则,抽象类和接口是一个契约,改变契约,所有与契约有关系的代码都要修改。
工厂总结
- 简单工厂模式是由一个具体的类去创建其他类的实例,父类是相同的,具体的。
- 工厂方法模式是有一个抽象的父类定义公共接口,子类负责生成具体的对象,目的是将类的实例化操作延迟到子类中完成针对的是一个产品的等级结构。
- 抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无须指定他们具体的类。针对有多个产品的等级结构
相同点:模式的使用者Client都只需要关心抽象的工厂类或者抽象的产品类,而把创建何种产品的问题交给工厂类(或其子类)解决,增加了系统的灵活性
不同点
- 简单工厂 :是通过工厂类自身接受其调用者Client传入的参数来判断创建何种产品
- 工厂方法 :则用到了面向对象中的继承特性,通过继承抽象类的方法,将产品的创建延迟到子类中实现
- 抽象工厂:原理与工厂方法模式相同,只是关注的是创建一系列相关或者相互依赖的对象
建造者模式:
将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象。
优点
- 各个具体的建造者相互独立,有利于系统的扩展。
- 客户端不必知道产品内部组成的细节,便于控制细节风险。
- 客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使相同的创建过程可创建不同的产品对象。
- 每个具体建造者都相对独立,与其他的具体建造者无关,因此可很方便地替换具体建造者或增加新的具体建造者,用户用不同的具体建造者即可得到不同的产品对象。更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”。
缺点
- 产品的组成部分必须相同,这限制了其使用范围。
- 如果产品的内部变化复杂,该模式会增加很多的建造者类
角色
- 产品角色:它是包含多个组成部件的复杂对象,由具体建造者来创建其各个部件。
- 抽象建造者:它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。
- 具体建造者:实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。
- 指挥者:它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IoUA9WEx-1669205515114)(…/…/.config/Typora/typora-user-images/image-20221123191033733.png)]
结构型
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。
代理模式(Proxy) :
由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象
适配器模式(Adapter)
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
类别
类结构型模式
- 实现:类适配器模式可采用多重继承方式实现,如 C++ 可定义一个适配器类来同时继承当前系统的业务接口和现有组件库中已经存在的组件接口;Java 不支持多继承,但可以定义一个适配器类来实现当前系统的业务接口,同时又继承现有组件库中已经存在的组件Adapter 类继承Adaptee (被适配类),同时实现Target 接口(因为 Java 不支持多继承,所以只能通过接口的方法来实现多继承),在 Client 类中我们可以根据需要选择并创建任一种符合需求的子类,来实现具体功能
- 优点:由于适配器类是适配者类的子类,因此可以在适配器类中置换一些适配者的方法,使得适配器的灵活性更强
- 缺点:对Java、C#等不支持多重继承的语言,一次最多只能适配一个适配者类,且目标抽象类只能为抽象类,不能为具体类,其使用有一定的局限性,不能将一个适配者类和它的子类都适配到目标接口
对象结构型模式
- 实现:对象适配器模式可釆用将现有组件库中已经实现的组件引入适配器类中,该类同时实现当前系统的业务接口;不使用多继承或继承的方式,而是使用直接关联,或者称为委托的方式
- 优点:一个对象适配器可以把多个不同的适配者适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口
- 缺点:与类适配器模式相比,要想置换适配者类的方法就不容易。如一定要置换掉适配者类的一个或多个方法,就只好先做一个适配者类的子类,将适配者类的方法置换掉,然后再把适配者类的子类当做真正的适配者进行适配,实现过程复杂
区别
- 类适配器的重点在于类,是通过构造一个继承Adaptee类来实现适配器的功能;
- 对象适配器的重点在于对象,是通过在直接包含Adaptee类来实现的,当需要调用特殊功能的时候直接使用Adapter中包含的那个Adaptee对象来调用特殊功能的方法即可
优点
- 客户端通过适配器可以透明地调用目标接口。
- 复用了现存的类,程序员不需要修改原有代码而重用现有的适配者类。
- 将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题。
缺点:对类适配器来说,更换适配器的实现过程比较复杂
角色
- 目标接口:当前系统业务所期待的接口,它可以是抽象类或接口。
- 适配者类:它是被访问和适配的现存组件库中的组件接口。
- 适配器类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。
适用
- 以前开发的系统存在满足新系统功能需求的类,但其接口同新系统的接口不一致。
- 使用第三方提供的组件,但组件接口定义和自己要求的接口定义不同
扩展:适配器模式(Adapter)可扩展为双向适配器模式,双向适配器类既可以把适配者接口转换成目标接口,也可以把目标接口转换成适配者接口
桥接模式(Bridge)
将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度
组合模式(Composite)
有时又叫作部分-整体模式,它是一种将对象组合成树状的层次结构的模式,用来表示“部分-整体”的关系,使用户对单个对象和组合对象具有一致的访问性
优点
- 组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码;
- 更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”
缺点
- 设计较复杂,客户端需要花更多时间理清类之间的层次关系;
- 不容易限制容器中的构件
- 不容易用继承的方法来增加构件的新功能
角色
- 抽象构件角色:它的主要作用是为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。在透明式的组合模式中抽象构件还声明访问和管理子类的接口;在安全式的组合模式中不声明访问和管理子类的接口,管理工作由树枝构件完成。
- 树叶构件角色:是组合中的叶节点对象,它没有子节点,用于实现抽象构件角色中 声明的公共接口。
- 树枝构件角色:是组合中的分支节点对象,它有子节点。它实现了抽象构件角色中声明的接口,它的主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法
分类
- 透明式的组合模式:在该方式中,由于抽象构件声明了所有子类中的全部方法,所以客户端无须区别树叶对象和树枝对象,对客户端来说是透明的。但其缺点是:树叶构件本来没有 Add()、Remove() 及 GetChild() 方法,却要实现它们(空实现或抛异常),这样会带来一些安全性问题
- 安全式的组合模式:在该方式中,将管理子构件的方法移到树枝构件中,抽象构件和树叶构件没有对子对象的管理方法,这样就避免了上一种方式的安全性问题,但由于叶子和分支有不同的接口,客户端在调用时要知道树叶对象和树枝对象的存在,所以失去了透明性
应用
- 在需要表示一个对象整体与部分的层次结构的场合。
- 要求对用户隐藏组合对象与单个对象的不同,用户可以用统一的接口使用组合结构中的所有对象的场合
装饰模式(Decorator)
指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式
外观模式(Facade)
是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。
该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体的细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。
享元模式(Flyweight)
如一个软件系统在运行时所创建的相同或相似对象数量太多,将导致运行代价过高,带来系统资源浪费、性能下降等问题
如何避免系统中出现大量相同或相似的对象,同时又不影响客户端程序通过面向对象的方式对这些对象进行操作呢?
运用共享技术有效地支持大量细粒度的对象。
行为型
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配
行为型模式分为(类行为模式)和(对象行为模式),前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性
模板方法模式:
定义一个操作中的算法骨架,将算法的一些步骤延迟到子类中,使得子类在可以不改变该算法结构的情况下重定义该算法的某些特定步骤。是类行为模式
结构与实现
- 抽象类:负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。这些方法的定义如下
- 模板方法:定义了算法的骨架,按某种顺序调用其包含的基本方法
- 基本方法:是整个算法中的一个步骤,包含以下几种类型
- 抽象方法:在抽象类中申明,由具体子类实现。
- 具体方法:在抽象类中已经实现,在具体子类中可以继承或重写它。
- 钩子方法:在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种
钩子方法是对于抽象方法或者接口中定义的方法的一个空实现,比如说有一个接口,这个接口中定义了很多个方法,而你想实现其中某一个方法,这个时候就可以写一个抽象类实现这个接口,在这个抽象类里将你要用的那个方法设置为abstract,其它方法进行空实现,然后再继承这个抽象类,就不需要实现其它不用的方法,这就是钩子方法的作用。
- 具体子类:实现抽象类中所定义的抽象方法和钩子方法,它们是一个顶级逻辑的一个组成步骤
优点
- 它封装了不变部分,扩展可变部分。它把认为是不变部分的算法封装到父类中实现,而把可变部分算法由子类继承实现,便于子类继续扩展。
- 它在父类中提取了公共的部分代码,便于代码复用。
- 部分方法是由子类实现的,因此子类可以通过扩展方式增加相应的功能,符合开闭原则
缺点
- 对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象。
- 父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,它提高了代码阅读的难度
策略模式:
定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。
角色
- 环境角色:持有一个Strategy类的引用
- 抽象策略:一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口
- 具体策略:包装了相关的算法或行为
适用
- 多个类只区别在表现行为不同,可使用Strategy模式,在运行时动态让对象选择具体要执行的一种行为
- 要在不同情况下使用不同的策略(算法),动态的选择一种算法,或者策略还可能在未来用其它方式来实现
- 对客户隐藏具体策略(算法)的实现细节或算法使用的数据,彼此完全独立
优点
- 提供了一种替代继承的方法,保持继承的优点,比继承更灵活
- 避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。
- 提供了管理相关的算法族的方法,使这些算法可以相互替换,自由切换。
- 遵守大部分原则
- 简化了单元测试,因每个算法都有自己的类,可以通过自己的接口单独测试
缺点
- 所有的策略模式都需要对外暴露客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
- 造成很多的策略类
- 只适合扁平的算法结构,不适合于处理同时嵌套多于一个算法的情形。
命令模式(动作模式):
将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化;对请求 排队或 记录请求日志,以及支持可撤销的操作.是对象行为型模式,别名为动作(Action)模式或事务(Transaction)模式
角色
- Command: 抽象命令类
- ConcreteCommand: 具体命令类
- Invoker: 调用者
- Receiver: 接收者
- Client:客户类
优点
- 降低系统耦合度
- 新命令可很容易加入到系统中
- 较易设计一个命令队列和宏命令(组合命令)
- 可方便地实现对请求的Undo和Redo
缺点:导致某些系统有过多的具体命令类。因为针对每个命令都需要设计一个具体命令类,大量具体命令类,影响模式的使用
适用性
- 系统要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
- 系统要在不同的时间指定请求、将请求排队和执行请求。
- 系统要支持命令的撤销(Undo)操作和恢复(Redo)操作。
- 系统要将一组操作组合在一起,即支持宏命令
职责链模式:
把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。
角色
- 抽象处理者(Handler):定义出一个处理请求的接口。如需要,接口可定义 出一个方法以设定和返回对下家的引用。通常由1个Java抽象类或接口实现。Handler类的聚合关系给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作。
- 具体处理者(ConcreteHandler):它接到请求后,可选择将请求处理掉,或将请求传给下家。由于具体处理者持有对下家的引用,如需要,它可访问下家
优点
- 解耦 : 请求的 发送者 和 接收者 解耦 ; 接收者 是 请求的处理者 ;
- 动态组合 : 责任链 可以 动态组合 , 使用配置 设置责任链的 顺序及 是否出现 ; 可以随时对责任链排序 , 随时增加拆除责任链中的某个请求对象 ;
缺点
- 性能 : 如果 责任链 太长 , 或责任链中请求的 处理时间过长 , 可能会 影响性能 ;
- 个数 : 责任链 可能过多
适用
- 有多个对象可处理一个请求,哪个对象处理该请求在运行时刻自动确定。
- 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求
状态模式:
允许一个对象在其内部状态发生改变时改变其行为能力。
状态模式和策略模式的区别
如果你看看状态模式和策略模式的UML图,就会发现它们的结构非常相似。使用State对象改变自己行为的对象被称为Context对象;相似的,使用Strategy对象改变自己行为的对象叫Context对象。记住,Client和Context打交道。在状态模式中,Context把方法调用委托给当前的状态对象,而在策略模式中,Context使用的Strategy对象,是被当做参数传递过来的,或在Context对象被创建时就被提供的。
每一个状态都持有Context的引用,用它来管理由Context触发的行为导致的状态转移。
让我们来看看它们之间更多的相似之处:
- 添加新的状态或策略都很容易,而且不需要修改使用它们的Context对象。
- 它们都让你的代码符合OCP原则。在状态模式和策略模式中,Context对象对修改是关闭的,添加新的状态或策略,都不需要修改Context。
- 正如状态模式中的Context会有初始状态一样,策略模式同样有默认策略。
- 状态模式以不同的状态封装不同的行为,而策略模式以不同的策略封装不同的行为。
- 它们都依赖子类去实现相关行为。
不同之处
现在我们知道,状态模式和策略模式的结构是相似的,但它们的意图不同。让我们重温一下它们的主要不同之处:
- 策略模式封装了一组相关算法,它允许Client在运行时使用可互换的行为;状态模式帮助一个类在不同的状态显示不同的行为。
- 状态模式封装了对象的状态,而策略模式封装算法或策略。因为状态是跟对象密切相关的,它不能被重用;而通过从Context中分离出策略或算法,我们可以重用它们。
- 在状态模式中,每个状态通过持有Context的引用,来实现状态转移;但是每个策略都不持有Context的引用,它们只是被Context使用。
- 策略实现可以作为参数传递给使用它的对象,例如Collections.sort(),它的参数包含一个Comparator策略。另一方面,状态是Context对象自己的一部分,随着时间的推移,Context对象从一个状态转移到另一个状态。
- 虽然它们都符合OCP原则,策略模式也符合SRP原则(单一职责原则),因为每个策略都封装自己的算法,且不依赖其他策略。一个策略的改变,并不会导致其他策略的变化。
- 另一个理论上的不同:策略模式定义了对象“怎么做”的部分。例如,排序对象怎么对数据排序。状态模式定义了对象“是什么”和“什么时候做”的部分。例如,对象处于什么状态,什么时候处在某个特定的状态。
- 状态模式中很好的定义了状态转移的次序;而策略模式并无此需要:Client可以自由的选择任何策略。
- 一些常见的策略模式的例子是封装算法,例如排序算法,加密算法或者压缩算法。如果你看到你的代码需要使用不同类型的相关算法,那么考虑使用策略模式吧。而识别何时使用状态模式是很简单的:如果你需要管理状态和状态转移,但不想使用大量嵌套的条件语句,那么就是它了。
- 最后但最重要的一个不同之处是,策略的改变由Client完成;而状态的改变,由Context或状态自己。
观察者模式:
多个对象间存在一对多关系,当一个对象发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行为。
中介者模式:
定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。
迭代器模式:
提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。
访问者模式:
在不改变集合元素的前提下,为一个集合中的每个元素提供多种访问方式,即每个元素有多个访问者对象访问。
备忘录模式:
在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它。
解释器模式:
提供如何定义语言的文法,以及对语言句子的解释方法,即解释器。是类行为模式
第 7 章 安全设计