第壹章 绪论
1.1 系统的概念和特性
概念
系统是一组为实现某些结果相互联系、相互作用的部件的集合体。
特性
- 系统具有整体性,系统的整体功能大于组成系统的各部分的功能之和。
- 系统具有目的性,一般通过更具体的目标来实现,系统的多个目标有时不完全一致,甚至互相矛盾,这就需要协调,需求平衡或折中的办法,从而收到整体最佳效果。
- 系统具有相关性,系统内各部分之间存在着相互依赖和相互制约的特定关系,某个部分的变化会影响其他部分的实现功能。
- 系统具有环境适应性 系统具有适应环境的变化,保持原有功能的特性。
- 系统具有层次性,系统可以分解为一系列的子系统,并存在一定的层次结构。系统各个层次具有独立的功能,他们通过相互联系、相互作用共同完成系统的功能。
系统分析
是对一种业务问题域的学习活动,能够在系统解决方案中为提升系统性能和明确业务需求提供良好的建议。(理解问题域) 系统分析的出发点是为了发挥系统整体功能,目的是寻求解决问题的最佳决策。
系统设计
概念:是对系统分析中已确定的业务需求的说明或者构建一种相关技术的解决方案。
步骤:
- 明确问题,设立目标
- 收集资料,制定方案
- 分析计算,评价比较
- 检验核实,作出决策
第贰章 系统规划
2.1 系统规划概述
系统的生命周期
成功的系统的标准 (ERP)
- 客户接收最后得到的信息系统
- “及时”交付了系统
- “在预算内”交付了系统
- 系统开发过程对正在进行的企业运营影响很小
成功的系统的原因
- 有充分的系统需求定义
- 用户的充分参与
- 上层领导的高度支持
- 完整、详细的项目计划
- 符合实际的工作进度表
失败的系统的原因
- 没有切实了解系统需求
- 用户参与不充分
- 缺少高层领导的支持和协调
- 目标不清楚
- 缺少所需资源
系统规划
定义
根据组织的战略目标和用户提出的需求,从用户的现状出发,经过调查,对所要开发信息系统的技术方案、实施过程、阶段划分、开发组织和开发队伍、投资规模、资金来源及工作进度,用系统的、科学的、发展的观点进行全面规划。
- 系统规划是系统开发的前提条件
- 系统规划是系统开发的提纲
- 系统规划是系统开发成功的保证
- 系统规划是系统验收评价的标准
系统规划原则
- 自顶向下的规划策略
- 第一把手参与
- 支持企业总的目标
- 摆脱信息系统对组织的依赖性
- 先进性、开放性
- 可靠性
- 安全性
- 可扩充性
系统规划目标
根据组织的目标与战略制定出信息系统的目标与发展战略,确定信息提供建设的长期发展方案,决定信息系统在整个生命周期内的发展方向、规模和发展进程。
系统规划任务
系统规划阶段模型
系统战略规划
业务流程重组(BPR)
系统总体结构规划
- 组织的信息需求分析
- 系统数据规划
- 功能规划与子系统划分
- 信息资源配置规划
项目实施与资源分配规划
- 制定项目实施规划
- 制定资源分配方案
规划方案的可行性研究
2.2系统规划步骤
- 对当前系统进行初步调查
- 分析和确定新系统目标
- 分析子系统组成和功能
- 拟定系统实施方案
- 进行可行性研究
定义管理目标: 调查了解组织结构, 达到目标采取的经营方针 实现该目标的约束条件
2.3规划模型
诺兰模型
CMM模型
用来评估组织的信息系统开发以及管理过程和产品的成熟度等级的框架。由5个开发等级,用一组被称为关键过程领域的指导方针进行度量。
流程图
分级
作用和目的
用途
意义
2.4规划方法(BSP,U/C矩阵)
2.4.1 战略集合转换法( Strategy Set Transformation, SST)
定义
把整个战略目标看成是一个“信息集合”,由使命、目标、战略和其他战略变量(如管理的复杂性、改革习惯以及重要的环境约束)等组成。 MIS的战略规划过程是把组织的战略目标转化为管理信息系统战略目标的方法。
步骤
识别组织的战略集
① 描绘出组织各类人员或实体结构
② 识别每类人员或实体的目标
③ 对于每类人员或实体识别系统相应的使命及战略
将组织战略集转化为信息系统战略
① 根据组织目标确定信息系统目标
② 对应组织战略集的元素识别相应信息系统战略的约束
③ 根据信息系统目标和约束提出信息系统战略
CSF
通过分析找出使得企业成功的关键因素,然后再围绕这些关键因素来确定系统的需求,并进行规划。
实施步骤
- 了解企业或MIS的战略目标
- 识别所有的成功因素
- 确定关键成功因素
- 明确各关键成功因素的性能指标和评估标准
基本流程
2.4.2 关键成功因素法( Critical Success Factors, CSF)
头脑风暴
鱼骨图
类型
适用步骤
2.4.3 企业资源规划法BSP( Business System Planning, BSP)
定义
为指导企业管理信息系统的开发而建立的规范方法。用于企业内部系统开发。先自上而下识别系统目标、识别企业的过程、识别数据,然后再自下而上地设计系统目标,最后把企业目标转为信息系统规划的全过程。 根据企业目标制定出MIS战略规划的结构化方法
出发点
- 1. 系统必要支持企业目标。
- 2. 系统战略应表达企业各个管理层要求。
- 3. 应向整个组织提供一致性信息。
- 4. 应在组织机构和管理机制改变时保持工作能力。
- 5. 系统战略规划应由总体系统中的子系统开始实现
工作策略
核心步骤
具体步骤
l、准备工作。
- 成立规划领导小组
- 提出工作计划
- 开动员会
2、调研,动员,定义目标
- 为后续需要完成的任务内容进行必须的了解
- 可以通过多种方式进行,如访谈、问卷、现场观察记录、文献研究、实验,头脑风暴等
3、定义业务过程(又称企业过程或管理功能组)
- BSP方法的核心
- 定义:管理中必要且逻辑上相关的、为了完成某种管理功能的一组活动
- 识别业务过程(企业过程,功能组)的主要意义
- 整个企业的管理活动由许多业务过程组成,识别它会对企业如何完成其目标产生深刻了解
- 作为信息识别和构成信息系统的基础
- 按照企业过程所创建的信息系统,在企业组织机构变化时可不必改变,即信息系统相对独立于组织
过程
思路和步骤 企业活动一般由三个方面组成
(1)计划和控制: 企业计划和控制有关的业务过程一般分为战略规划和管理控制两大类
(2)产品和服务
A 按产品/服务的生命周期的各个阶段识别过程
B 画出产品/服务过程的总流程图,写出每个过程的说明:生产计划,采购 A 任何产品的生命周期,可分为需求、获取、服务、退出四阶段,可对每个阶段的业务过程 分析列表。
企业产品与服务方面业务过程识别后进一步表达
(3)支持资源
(4)归纳和分析
- 过程归并
- 归并后画出过程组合表和过程说明
- 建立企业过程与组织联系
- 识别关键过程
建立企业过程和组织关系 过程/组织矩阵
(5) 结果与应用
- 给过程起名
- 一个过程组及过程表(过程目录)
- 每一过程的简单说明
- 一个过程关键的表,即识别满足目标的关键过程产品/服务过程流程图
- 系统规划组成员对企业运营的管理和控制过程的深入理解
图示步骤,可归纳出企业的业务过程集合
4、业务过程重组。
在业务过程识别的基础下,明确
- 哪些业务过程是正确的
- 哪些业务过程低效,需要在信息技术支持下实现优化
- 哪些业务过程无效,或不适合于计算机处理,应当在业务中予以取消
5、定义数据类。
定义
指支持业务过程所必需的逻辑相关的数据。
识别数据类的目的在于了解企业目前的数据状况和数据要求,以及数据与企业实体、业务过程之间的联系,查明数据共享的情况,建立功能/数据类矩阵,为定义信息系统总体结构提供基本依据。
其中:企业实体指企业实施管理的对象,一般可按人、地点、物体、概念和事件进行分类,如企业员工、设备、产品和材料等。
方法
实体法 功能法
实体法:
根据资源(实体即资源)的管理过程可以将数据分解成四类, 每个实体可以由这四种数据类型来描述。
- 计划型——反映目标的计划值;
- 统计型——反映企业的综合状况;
- 文档型——反映实体的现状;
- 业务型——反映生命周期各阶段相关文档型数据的变化
绘制实体资源(资源)/数据类矩阵
功能法:
6、定义信息系统总体结构。
划分子系统。BSP方法将过程和数据类两者作为定义企业信息系统总体结构的基础,用过程/数据矩阵(也称U/C矩阵)表达两者之间的关系。
行表示数据类,列表示过程,字母U(use)和C(create)来表示过程对数据类的使用和产生。
价值链分析法
7、确定总体结构中的优先顺序
8、完成BSP研究报告,提出建议书和开发计划
第叁章 系统分析
3.1 系统分析概述
3.1.1 系统分析概述
概念
系统分析将一个系统分解成各个组成部分,目的是研究各部分如何工作,如何交互,以实现系统的目标。 用模型和其他文档工具来呈现和描述所建议的系统。
任务
将系统详细调查中所得到的文档资料,对组织内部整体管理状况和信息处理过程 分析,研究业务领域,定义业务的优先级。借助于当前系统的逻辑模型导出目标系统的逻辑模型,解决目标系统 “做什么” 的问题
目的
将需求及解决方法确定下来,建立逻辑模型
分析内容:业务和数据的流程是否通畅,是否合理;数据、业务过程和实现管理功能之间的关系。
需求的三个层次:业务需求,用户需求,系统需求
需求的分类
- 功能(包括数据要求和加工要求,和系统主要工作相关的需求)
- 非功能(性能,质量属性,接口,约束)
3.1.2 分析实现步骤
3.2 结构化系统分析
业务流程图
带泳道的:泳道图在某些文档里会被称为“以活动为单位的流程图”,浮在泳道中的都是一个个活动。突出活动关系,表示各部门的责任
顾客提交订单给销售部门,销售部门经过订单检查,把不合格的订单反馈给顾客,对合格订单,通过核对库存记录,缺货订单通过缺货统计,向采购部门发出缺货通知,并登记缺货记录。对于可供货订单,登记客户档案,开出备货单,通知仓库备货。同时保存订单数据,并进行销售统计。
系统流程图
变换
把输入单据变换成磁盘文件,或把磁盘文件变换成输出单据,或把某一磁盘文件的内容由一个介质文件传送到另一介质文件
一般在在进行输入变换同时,还可进行形式性的逻辑检查,如输入单据的数据范围,录入错误等等。
划分
是合并的逆操作,将合并工序的输入文件与输出文件对调即可
更新
将多个文件作为输入根据关键项目进行对照,对文件进行内容修正、删除、增加等改写工作,一般更新的内容先要写入一个临时文件
第肆章 系统分析
4.1 系统设计内容
系统设计内容
比如
功能
性能
过程设计(处理流程)
运行环境
用户界面设计
关键技术和算法
数据库,数据结构
安全性,保密性
为响应需求做出的其他系统级的设计决策
系统架构设计:总体,层次结构,部件,接口,动态交互
输入输出(I/O):对输入或条件进行响应的系统行为的设计决策
硬件
代码设计
系统配置项设计,人工处理等
运行设计
出错处理设计
系统维护设计
4.2 系统设计原则
- 1组件化
- 2 抽象化
- 3内聚和耦合
- 4封装与隐蔽
- 5 启发式规则 A 深度,宽度,扇出,扇入。B 作用域和控制域 C 可预测性
- 6 完整性,正确性,够用原则,逐步求精,可双向跟踪,一致性,集成性,健壮性,可靠性,容错性,无歧义,模块独立性,架构稳定性,可扩展性,可复用性。
抽象化
面向抽象编程,是指当设计一个类时,不让该类面向具体的类,而是面向抽象类或接口,即所设计类中的重要数据是抽象类或接口声明的变量,而不是具体类声明的变量。
- 软件系统进行模块设计时,可有不同的抽象层次。
- 在最高的抽象层次上,可以使用问题所处环境的语言概括地描述问题的解法。
- 在较低的抽象层次上,则采用过程化的方法。
(1)过程的抽象
从系统定义到实现,每进展一步都可看做是对软件解决方法的抽象化过程的一次细化。
需求分析阶段,用“问题所处环境的、为大家所熟悉的术语来描述软件的解决方法。
从概要设计到详细设计,抽象化的层次逐次降低。产生源程序时到达最低抽象层次。
(2)数据抽象
在不同层次上描述数据对象的细节,定义与该数据对象相关的操作。 如CAD软件中,定义一个叫做drawing的数据对象。可将drawing规定为一个抽象数据类型,定义它的内部细节为:
数据抽象drawing本身由另外一些数据抽象,如geometry、BOM (bill of materials) 构成 定义drawing的抽象数据类型后可引用它来定义其它数据对象,而不必涉及drawing的内部细节,如,定义: blue-print IS INSTANCE OF drawing;
内聚
偶然内聚,逻辑内聚,瞬时内聚,过程内聚,通信内聚(使用公共数据),顺序内聚,功能内聚。
耦合
内容耦合,公共耦合,外部耦合,控制耦合,标记耦合,数据耦合,非直接耦合。
4.3 系统设计优化
定义
指在给定条件(或约束)下,根据系统的优化目标,采取一定的手段和方法,使系统的目标值达到最大化(或最小化)。
优化意义
以最小的投入,获取系统的最佳效益或最佳功能。
考虑因素
- 系统设计的目的与要求。
- 系统各部分之间的相互联系与相互作用。
- 系统设计方案的优化。
系统设计要从整体出发,以系统整体功能的最优为目的,运用系统的思想综合考虑各部分之间的关联、冲突问题,注重各部分的横向、纵向联系。
第陆章 面向对象的设计
6.1 面向对象设计概述
对象技术是软件技术,采用封装数据和行为的对象来定义系统
可复用,可扩展,c++,java,Smalltalk都是
面向对象分析和设计方法,利用对象技术来构造系统及其软件
敏捷开发 从一套相应的工具和技术中灵活地选择最适合完成任务的工具和技术,可以在系统开发的产量和质量之间达到最优化平衡
静态模型包括: 类图,对象图,包图
行为图:描述系统的动态模型;
交互图:描述对象间的交互关系。
类的分类:
按名词短语分类:相关类,模糊类,无关类
按公共类模式分:概念类,事件类,组织类,人员类,地点类。
按功能:实体,边界类(接口等),控制类(这3也叫识别类),系统类,持续类
还有:物理类,业务类,逻辑类,应用类,计算机类,行为类
据备选构架定义三类分析类, UML可描述三个主要的类
边界类:系统及其参与者的边界,是信息或响应事件,代表系统和环境的交互,是接口和外部事物的中间体,构造型<<boundary>>
两类:
- 用户界面类: 关注展示给用户的信息,不关注用户界面的细节。
- 系统和设备接口类: 关注系统必须定义的协议,不关注协议如何实现。
控制类:系统的控制逻辑,系统行为的协调器,构造型<<control>>,识别控制类:开发早期,为每一个用例定义一个控制类,负责该用例的控制逻辑,针对复杂用例,可为备选路径分别定义不同控制类。
隔离和协调边界类和实体类。当用例复杂时(如有分支的事件流),一个用例可以有控制类,本身不处理具体任务,而是调度其它类完成具体的任务。
实体类:系统使用的信息,用例中的参与对象,对应现实世界中的事物,实体代表开发系统的核心概念,实体类提供了另一个理解系统的观点,描述必须存储信息及其相关行为。(显示系统的逻辑数据结构,传统面向对象方法就是从这个角度分析和设计的) 构造型是<<entity>>
用例事件流(需求),业务模型(业务建模),词汇表(需求)
实体类的识别质量,取决于文档的风格和质量。来源于用例文档,访谈信息,系统原始需求书/问题描述
边界类和实体类的交互
- 实体类仅负责数据的输入和输出,不承担和数据处理有关的业务逻辑,可负责不大复杂的数据校验功能。
- 边界类通过与实体类的交互,获得相关数据处理的结果。
属性描述:
描述类在软件系统中对象所具备特性,是所有对象共有,是某个对象的逻辑数据值。
- 类有任意数目的属性,也可没有属性。所有对象共享的属性是类属性,用下划线标识
- 语法: 可见性 属性名 [ 多重性 ] : 类型 [ = 初始值 ]
可见性,常和继承关系一起使用,只能被本类及派生类使用,允许子类访问父类中受保护类型的属性。
public公有,private私有,protected受保护
-
尽可能将所有属性设置为private;
-
仅通过set方法更新属性;
-
仅通过get方法访问属性;
属性,描述其所属类的特性的名词或名词短语构成,1个标识符,属性的名称的第一个字母小写,如果包含多个单词,这些单词要合并,且除了第一个英文单词外,其余单词首字母大写
属性类型:该属性的数据类型。可是系统固有的类型,如整型、实型等,也可是用户自定义的类型
具有单值属性,互斥,多值的特性
1)简单类型:数字Number、字符串String 、日期Date 、时间Time 、文本Text,整型,布尔型,实型
2) 其他常见的类型: 地址Address、颜色Color、几何元素Geometrics、 电话号 PhoneNumber、通用商品代码UPC、 社会安全代码Social Security Number、邮政编码Postal Code 、枚举类型等
消息传递:
类的操作
描述系统中所代表的对象具备的动态部分的公共特征抽象,一个类可以有任意数量操作或没操作,且每个操作只应用于该类的对象,属性是描述类的对象特性的值,而操作用于操纵属性的值进行改变或者执行其他动作。
类操作的分类: 对象操作:创建、初始化、维护、删除对象
计算操作:完成某种算法的操作
监控操作:为了控制事件的发生而监控对象的操作
类之间的关系
关联(拥有, ASSOSATION,使用实例连接/单,双,自,弱)
常表示拥有对其他对象的引用的实例变量。
分析中的关联无导航性,是增进对问题的理解为目的。
设计类图中的关联有导航性,是对软件构件的描述。设计类图中导航是角色的一个特性,它说明从源对象到目标对象沿着关联有一个单向的链接。
两个类之间有关联,其关联关系可以通过在自己类的属性和操作定义中将相关联的类作为对象成员使用而体现出来。
在操作定义中体现了关联关系,将对象作为参数成员使用
通过发送消息调用相关联的类的操作。
1) 单项关联 指只有某一方拥有另一方的引用, 这样只有拥有对方者可以调用对方的公共属性和方法.
只有一个类知道另外一个类的公共属性和操作。大多数关联应该是单向的,单向关系更容易建立和维护,有助于寻找可复用的类
通过在自己类的属性和操作定义中将相关联的类作为对象成员使用而体现出来。
在操作定义中也体现了关联关系,将对象作为参数成员使用。
也可以通过发送消息调用相关联的类的操作。
聚合(整体和部分关系,HAS A比关联 强,比组合 弱)
组合(整体和部分关系,合成关系, contains-a,部分不能离开整体)
泛化(一般和特殊关系(区别),继承, GENERALIZATION )
实现(拥有,类和接口的关系 Realization)
依赖(DEPENDENCY)
关联和聚合的区别:语义上,关联的两个对象之间一般是平等的
关联和泛化(类之间的语义关系)
标识对象之间的关联
【1】 建立实例连接(对象间的静态联系)
1 认识对象之间的静态关系(确定关联)
2 认识他们的属性和操作
3 分析实例连接的包含性,依赖,多重性
4 异常情况处理(多对多,多元关联)
5 命名与定位
对象之间的实例连接称为链接(Link)
把类之间的实例连接称为关联(Association)
【2】 消息传递 ( 动态)
对象之间的通信只能通过消息的发送和接收完成。
类型有: 激活,提供信息给,询问,命令,请求
筛选对象间的关联(复审类的定义)
原始性:删除衍生关联,即重复关联
单一性:删除多重关联关系
结构性:删除非结构的暂时性关系
相关性:删除与实际操作无关的关系
【3】 筛选对象间的关联
6.2 静态(对象)建模(类图)
接口
定义
是类 抽象类 特殊的抽象类
属性:
- 可以定义属性但不能实现,要初始化,需要实现它的类来实现
- 操作:抽象操作(只有操作名,没有体实现)
是描述类的部分行为的一组操作,它也是一个类提供给另一个类的一组操作。通常接口被描述为抽象操作,也就是只用标识(返回值、操作名称、参数表)说明它的行为,而真正实现部分放在使用该接口的对象中,也就是说接口只负责定义操作而不具体的实现。
接口是在没有给出对象的实现和状态的情况下对对象行为的描述。
抽象类和接口的相似和区别
抽象类:
- 声明方法的存在而不去实现它的类被叫做抽像类,用于创建一个体现某些基本行为的类,并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。但可以创建一个变量,其类型是一个抽像类,并让它指向具体子类的一个实例。
- 接口 抽象类的变体
接口是引用类型的,和抽象类的相似:
- 不能实例化;
- 包含未实现的方法声明;
- 位于继承层次的上层
- 派生类必须实现未实现的方法,抽象类是抽象方法,接口是所有成员
接口的优势
- 1 不只可以作用于引用类型还可以用于值类型,抽象类只能用于引用类型
- 2 通过接口实现多继承
- 3 可以被多个类型重用
- 4 减少暴露的属性和方法,保护类型对象
- 缺点:定义的方法,属性只能相对于继承它的类型。多层继承关系很难。
6.3 动态建模(顺序,合作)
顺序图
动态模型(行为建模)
- 通过分析,找出状态,发现服务
- 审查和调整
- 服务的命名和定位
- 服务的详细说明
建立动态模型,联系起来就是系统
顺序图描述对象间的交互行为(用例的行为顺序)
注重消息的时间顺序,对象间消息的发送和接收顺序
顺序图揭示一个特定场景的交互(系统执行期间发生某时刻的对象之间的特定交互),适合描述实时系统中的时间特性和时间约束
组成成分
对象: 对象框(短式),对象名需带下划线
生存线: 对象框下垂直虚线,表示生存时间
激活期: 细长方形框
消息:发送和接收两个对象生存线之间的消息箭头线
同步消息
发送者把进程控制传递给接收者,然后暂停活动,等待接收者放弃或者返回控制。
接收者执行请求操作,把控制传递给另一个对象角色,请求做某操作,完成后给原来同步消息的发送者,也可直接返回或发消息给原来的消息发送者。
异步消息
发送者和接收者采用并发工作方式
一条一步消息每次只发一个信号,只做一件事:
-》创建一个新对象
-》创建一个新进程,异步消息连接到一个激活期的顶部
-》与一个正在运行的线程通信
分支控制
顺序图: 实例形式,一般形式
分支: 条件分支,并发分支
约束
循环:
消亡:打叉
实例:
合作图
强调这组对象之间的关系,强调发送和接收消息的对象之间的结构组织的交互图,显示对象,对象之间的连接以及对象之间的消息
类元角色的对象所处的位置,显示了类元角色和关联角色、
对象和顺序图一样
链接: 参与协作执行的关联的描述 当协作被实例化,对象受限于类元角色,连接受限于关联角色
消息
约束
全局性:角色是全局的
局部性: 角色是一个操作中的局部变量
参数性: 角色是一个操作中的参数
自我性: 对象可以向自身发送消息
表决性: 通过约束回送消息
广播性: 一组消息的约束(系统中每个对象都是潜在的目标对象)
消息:描述系统的动态行为。
每个消息包括一个顺序号以及消息的名称
顺序号由1开始递增,每个消息都由唯一的顺序号,嵌套消息使用点表示法
链:对象间的发送信息的路径
创建和消亡
创建: {new};
消亡: {destoryed};
创建并消亡: {transient};
试例:可以嵌套使用消息标识,也可以使用顺序消息序号标识
回调:
循环发送:
通用的描述方法:
1:通用接口界面层
2: 系统业务对象层
3: 系统数据库层
构架图
物理方面建模时要用到的图,说明构件之间的逻辑关系
作用:
- 对源代码构建
- 对可执行体构建
- 从整体了解物理部件显示构件间关系
- 可调整的系统建模
构件:定义良好接口的物理实现单元,不直接依赖其他构件仅依赖构件所支持的接口。构件可避免在系统中与其它构件之间直接发生依赖关系
(1)接口:描述一个构件能提供服务的操作,位于两个构件中间,割断了它们间的依赖关系,使构件具有良好的封装性。给定的接口,可以被1个构件输出,也可被另一构件输入。一个构件可以既输出接口又输入接口。
(2)操作:构件通过消息传递方式进行操作,每个操作由输入输出变量、前置条件和后置条件来决定。前置条件,后置条件
(3)实例化:构件是个物理实体,实例化代表运行期间的可执行软件模块(类是逻辑抽象,可有多个实例)。
(4)与配置环境的亲合性:构件从内、外两方面满足于配置环境的相容性: 外部:利用配置环境提供的某组操作,降低构件的复杂程度。 内部:构件提供一组其配置环境需要的操作,达到亲合的目的。
(5)能与同环境下其它构件进行交互。能够调用其他构件也可以被其他构件使用。
(6)构件可以是可执行代码、二进制代码和源代码形式
(7)可替换的物理实体。构件是物理实体而不是逻辑概念,具有可替换性。
(8)系统的组成部分。很少独立存在,可多个系统中复用。
(9)构件是软件复用的基本单元。
接口:两个构件中间,斩断依赖关系,具有较好的封闭性
简单构件图:
用构件图建立系统模型(用途):
系统业务模型
系统开发管理模型
系统实现模型
系统物理配置模型
集成系统模型
构件描述的方法与技巧
(1)一个结构良好的构件应具备的特点
从物理结构上对软件系统进行抽象;
提供一组小的、定义完整的接口实现;
构件应包含与其功能有关的一组类,以便满足接口要求;
与其它构件相对独立,构件之间一般只有依赖和实现的关系。
(2)绘制构件时的技巧
为构件标识一个能准确表达其意义的名字;
接口一般采用短式图符表示;
只在必须显示接口的操作(不展示不能清楚描述构件的功能)时才用长式表示;
只显示那些对理解构件功能有重要影响的接口;
构件为源代码或库时,显示有关版本标记。
构件图描述的技巧
(1)一个结构良好的构件图应具备的特点
侧重描述系统静态视图的某一侧面;
只包含那些对描述该侧面内容有关的模型元素;
提供与抽象层次一致的描述,只显示有助于理解该构件图的必要的修饰;
图形不要过于简化,以防产生误解。
(2)绘制一个构件图时应注意的问题
为构件图标识一个能准确表达其意义的名字;
摆好各个构件的位置,尽量避免连接线的交叉;
语义相近的模型元素尽量靠近; 用注解和颜色提示重点部位;
谨慎采用自定义构造型元素;
采用尽量少的图符标记描述构件图,保持所有构件图风格一致。
部署图
结点:
既可看作类型,也可看作实例
短式
长式:
结点名 结点属性 结点上的构件
结点上的构件: 驻留并执行 两种表述形式
《支持》表示可以在这个结点实例(即目标工作站实例)上执行这个构件实例
节点与组件的比较:
每一个模型中仅包含一个部署图
结点和构件间的依赖联系:驻留在某一结点上的构件或对象与另一个结点上的构件或对象之间可以发生联系,称为依赖。 “支持”依赖(一个结点和其内部构件) “成为”依赖(不同结点内部构件或对象之间)
医院诊疗综合管理系统的用例图:
诊疗子系统的用例图:
“影像诊断”的详细构件图
硬件体系结构 :“诊疗管理”子系统配置图:
“影像诊断”配置图:
7个设计原则
总原则
抽象和复用(封装、信息隐藏)
松耦合
面向功能模块
设计功能内聚的模块,避免使用全局数据
模块传递的参数作数据用,并且尽可能少
面向对象
单一职责,开放封闭,里氏替换
面向服务
标准化服务合约,服务松散耦合,服务抽象,服务可复用,服务自治,服务无状态,服务可发现性和服务可组合性。
1)单一职责原则(SRP,Single-Responsibility Principle)
一个设计元素只做一件事,不让类多功能化。
1)如果应用程序影响到类中某一种职责,应将他与其他职责分开。即分离类的职责,不要让一个类承担过多职责,避免设计脆弱
2 )接口:接口程序有两个职责: 调制解调器的连接处理; 两个函数的数据通信。
2)开闭原则(OCP,The Open-Closed Principle)
核心思想:类,模块和函数(实体)对扩展开放,对修改关闭。通过扩展来实现变化,而不是通过修改已有代码实现变化。通过系统适应改变保持相对稳定,避免僵化设计。
最关键步骤是“抽象”
目标
- 对于扩展是开放的 模块行为可扩展,使其具有满足改变的新需求
- 对于更改是封闭的 不必改动模块的源代码或二进制代码(dll / jar文件)
3)里氏替换原则(LSP,Liskov-Substitution Principle)
-
子类型必须替代基类型
- 对“开闭”原则的补充
4)依赖倒置原则(DIP,Dependency-Inversion Principles)
改掉过程化高层依赖底层,变成抽象依赖细节。
针对接口编程,不针对实现编程。
使用接口和抽象类对返回值和变量说明
设计时,尽量从抽象类继承,而不是从具体类继承。继承等级树的所有叶子节点应当是具体类,而所有的树枝节点应当是抽象类或者接口。
1.可减少类间的耦合,提高系统的稳定性,减少并行开发引起的风险,提高代码的可读性和可维护性。
2.大型项目中体现明显。规避非技术性因素引起的问题。以轻松扩展。
3.是几个设计原则中最难实现的。是实现开闭原则的重要途径
高低层都使用接口
5)接口隔离原则(ISP, see Interface Segregation Principles)
尽量提供小接口。简单设计会过大。因为每个客户程序并不依赖于接口里的大部分
6)优先使用组合而不是继承原则(CARP)
在许多设计中,人们希望系统的类之间尽量是低耦合的关系,而不希望是强耦合关系。即在许多情况下需要避开继承的缺点,而需要组合的优点。
7)迪米特原则(LOD)
知识最少原则,不要和陌生人说话。
熟人好办事 即 一个对象应该对其他对象有尽可能少的了解。
即 两个类不必彼此直接通信。通过第三者调用对方的方法。
23个设计模式
设计模式的定义及意义 Design Pattern 描述在面向对象软件设计过程中针对特定问题的简洁而优雅的解决方案,是一套被反复使用的代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解和保证代码可靠性。
设计模式分类
根据目的分为三种:
- 创建型模式主要用于创建对象。
- 结构型模式主要用于处理类或对象的组合。
- 行为型模式主要用于描述对类或对象怎样交互和怎样分配职责
根据范围分两种:
- 类模式处理类和子类之间的关系,这些关系通过继承建立,在编译时刻就被确定下来,是属于静态的。
- 对象模式处理对象间的关系,这些关系在运行时刻变化,更具动态性。
组成
4个基本元素:名,问题,解决方案,效果
学习模式注意以下
(1) 模式名和分类 (2) 意图 (3) 别名 (4) 动机 (5) 适用性 (6) 结构(7)参与者(8)协作 9 效果(10) 实现(11) 代码示例 (12) 已知应用 (13) 相关模式
创建型模式(Creational Pattern)
“怎样创建对象?”
“将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节,对象的创建由相关的工厂来完成。就像我们去商场购买商品时,不需要知道商品是怎么生产出来一样,因为它们由专门的厂商生产。
1)单例模式:某个类只能生成一个实例,且该类能自行创建这个实例的一种模式。该类提供了一个全局访问点供外部获取该实例,其拓展是有限多例模式。
例如: Windows 的回收站、操作系统中的文件系统、多线程中的线程池、显卡的驱动程序对象、打印机的后台处理服务、应用程序的日志对象、数据库的连接池、网站的计数器、Web 应用的配置对象、应用程序中的对话框、系统中的缓存等常常被设计成单例。
特点
- 单例类只有一个实例对象;
- 该单例对象必须由单例类自行创建;
- 单例类对外提供一个访问该单例的全局访问点;
保证一个类仅有一个实例,并提供一个访问它的全局访问点。对象创建型模式。单例模式又名单件模式或单态模式。
单例模式的主要角色
- 单例类:包含一个实例且能自行创建这个实例的类。
- 访问类:使用单例的类。
Singleton 模式通常有两种实现形式。
第 1 种:懒汉式单例 该模式的特点是类加载时没有生成单例,只有当第一次调用 getlnstance 方法时才去创建这个单例。
注意:如果编写的是多线程程序,则不要删除上例代码中的关键字 volatile 和 synchronized,否则将存在线程非安全的问题。如果不删除这两个关键字就能保证线程安全,但是每次访问时都要同步,会影响性能,且消耗更多的资源,这是懒汉式单例的缺点。
懒汉模式下的创建美国总统:
第 2 种:饿汉式单例 该模式的特点是类一旦加载就创建一个单例,保证在调用 getInstance 方法之前单例已经存在了。
饿汉式单例在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以是线程安全的,可以直接用于多线程而不会出现问题。
饿汉形式下:创建猪八戒
优点:
- 提供了对唯一实例的受控访问。因为单例类封装了它的唯一实例,所以它可以严格控制客户怎样以及何时访问它,并为设计及开发团队提供了共享的概念。
- 由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象,单例模式无疑可以提高系统的性能。
- 允许可变数目的实例。可基于单例模式进行扩展,使用与单例控制相似的方法来获得指定个数的对象实例
缺点:
- 没有抽象层,因此单例类的扩展有很大困难。
- 单例类的职责过重,一定程度上违背了“单一职责原则”。因为单例类既充当了工厂角色,提供了工厂方法,同时又充当了产品角色,包含一些业务方法,将产品的创建和产品的本身的功能融合到一起。
- 滥用单例将带来负面问题,如为节省资源将数据库连接池对象设计为单例类,可会导致共享连接池对象的程序过多而出现连接池溢出;很多面向对象语言的运行环境都提供自动垃圾回收技术,因此,如实例化的对象长时间不被用,系统会认为是垃圾,会自动销毁并回收资源,下次利用时又将重新实例化,这将导致对象状态的丢失。
适用:
- 系统只需要一个实例对象,如系统要求提供一个唯一的序列号生成器,或者需要考虑资源消耗太大而只允许创建一个对象。
- 客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。
- 在一个系统中要求一个类只有一个实例时才应当使用单例模式。反过来,如果一个类可以有几个实例共存,就需要对单例模式进行改进,使之成为多例模式。
2)原型模式:将一个对象作为原型,通过对其进行复制而克隆出多个和原型类似的新实例。
tip:存在大量相同或相似对象的创建问题,如果用传统的构造函数来创建对象,会比较复杂且耗时耗资源,用原型模式生成对象就很高效,就像孙悟空拔下猴毛轻轻一吹就变出很多孙悟空一样简单。
定义
用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。在这里,原型实例指定了要创建的对象的种类。用这种方式创建对象非常高效,根本无须知道对象创建的细节。
主要角色
- 抽象原型类:规定了具体原型对象必须实现的接口。
- 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。
- 访问类:使用具体原型类中的 clone() 方法来复制新的对象
结构图
无须知道创建细节。通过将一个原型对象传给那个要进行创建的对象,使通其过请求原型对象拷贝原型自己来实现创建过程。
主要解决
在运行期建立和删除原型。
适用
当创建对象时,使用者不需要知道对象是如何创建的,只要复制一个已有对象,然后在其上面进行修改以得到自己想要的对象,这个时候可以采用原型模式。
1、当一个系统应独立于它的产品创建,构成和表示时。
2、当要实例化的类是在运行时刻指定时,例如,通过动态装载
3、为避免创建一个与产品类层次平行的工厂类层次时。
4、当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些
原因
- 资源优化场景 类初始化要消化非常多的资源,包括数据、硬件资源等。
- 性能和安全要求的场景 通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。
- 一个对象多个修改者的场景 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
优点
高效,动态地添加产品类,而且对整体结构没有影响。提供了简化的创建结构。
缺点
由于要给每个类都配备一个克隆的方法,就需要在设计时通盘考虑,因为在已有的类的基础上添加clone操作时比较困难的 必须修改其源代码,违背了“开闭原则”。编写较为复杂的代码。
3)工厂方法模式:定义一个用于创建产品的接口,由子类决定生产什么产品。
定义
定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。我们把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。如果要创建的产品不多,只要一个工厂类就可以完成,这种模式叫“简单工厂模式”,它不属于 GoF 的 23 种经典设计模式,它的缺点是增加新产品时会违背“开闭原则”
“工厂方法模式”是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。
优点
- 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程;
- 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;
缺点
每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。
主要角色
- 抽象工厂:提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法 newProduct() 来创建产品。
- 具体工厂:主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
- 抽象产品:定义了产品的规范,描述了产品的主要特性和功能。
- 具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间一一对应。
结构图
适用
- 客户只知道创建产品的工厂名,而不知道具体的产品名。如 TCL 电视工厂、海信电视工厂等。
- 创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。
- 客户不关心创建产品的细节,只关心产品的品牌。
4)抽象工厂模式:提供一个创建产品族的接口,其每个子类可以生产一系列相关的产品。
定义
是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。 抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品
- 抽象工厂是应对产品族概念
- 产品族:指位于不同产品等级结构(电冰箱,电视机)中,功能相关联的产品组成的家族。一般是位于不同的等级结构中的相同位置上。每个产品族中含有产品的数目,与产品等级结构的数目是相等的,形成一个二维的坐标系,水平坐标是产品等级结构,纵坐标是产品族。叫做相图
组成
由抽象工厂、具体工厂、抽象产品和具体产品等 4 个要素构成,但抽象工厂中方法个数不同,抽象产品的个数也不同。
结构图
抽象工厂模式的结构同工厂方法模式的结构相似,不同的是其产品的种类不止一个,所以创建产品的方法也不止一个。
解答
适用
- 当需要创建的对象是一系列相互关联或相互依赖的产品族时,如电器工厂中的电视机、洗衣机、空调等。
- 系统中有多个产品族,但每次只使用其中的某一族产品。如有人只喜欢穿某一个品牌的衣服和鞋。
- 系统中提供了产品的类库,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构。
优点
- 隔离了具体类的生产,使得客户并不需要知道什么被创建。
- 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
- 增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”
缺点
- 增加新的产品等级结构很复杂,需要修改抽象工厂和所有的具体工厂类。
- 如果要增加一个产品结构,改动大。抽象类要增加一个方法,然后,两个实现类都要改,严重违反开闭原则,抽象类和接口是一个契约,改变契约,所有与契约有关系的代码都要修改。
总结
- 简单工厂模式是由一个具体的类去创建其他类的实例,父类是相同的,具体的。
- 工厂方法模式是有一个抽象的父类定义公共接口,子类负责生成具体的对象,目的是将类的实例化操作延迟到子类中完成针对的是一个产品的等级结构。
- 抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无须指定他们具体的类。针对有多个产品的等级结构。
对比
相同点
模式的使用者Client都只需要关心抽象的工厂类或者抽象的产品类,而把创建何种产品的问题交给工厂类(或其子类)解决,增加了系统的灵活性
不同点
简单工厂 :是通过工厂类自身接受其调用者Client传入的参数来判断创建何种产品
工厂方法 :则用到了面向对象中的继承特性,通过继承抽象类的方法,将产品的创建延迟到子类中实现 抽象工厂:原理与工厂方法模式相同,只是关注的是创建一系列相关或者相互依赖的对象
5)建造者模式:将一个复杂对象分解成多个相对简单的部分,然后根据不同需要分别创建它们,最后构建成该复杂对象
定义
指将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。
优点
- 各个具体的建造者相互独立,有利于系统的扩展。
- 客户端不必知道产品内部组成的细节,便于控制细节风险。
缺点
- 产品的组成部分必须相同,这限制了其使用范围。
- 如果产品的内部变化复杂,该模式会增加很多的建造者类。
组成
建造者(Builder)模式由产品、抽象建造者、具体建造者、指挥者等 4 个要素构成。
- 产品角色:它是包含多个组成部件的复杂对象,由具体建造者来创建其各个部件。
- 抽象建造者:它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。
- 具体建造者:实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。
- 指挥者:它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。
特点
引入了一个指挥者类Director,该类的作用主要有两个:
一方面隔离了客户与生产过程;
另一方面负责控制产品的生成过程。
指挥者针对抽象建造者编程,客户端只需要知道具体建造者的类型,即可通过指挥者类调用建造者的相关方法,返回一个完整的产品对象。
结构图
实例
结构图
优点
- 客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使相同的创建过程可创建不同的产品对象。
- 每个具体建造者都相对独立,与其他的具体建造者无关,因此可很方便地替换具体建造者或增加新的具体建造者,用户用不同的具体建造者即可得到不同的产品对象。
- 更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
- 增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”。
缺点
- 所创建的产品具有较多的共同点,其组成部分相似,如产品间差异很大,则不适合用建造者,使用范围有限制。
- 如产品的内部变化复杂,可能导致要定义很多具体建造者类来实现变化,系统变庞大。
创建型模式对比
单例模式
代码:
结构图:
抽象工厂模式
代码:
建造者模式
结构型模式
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。
由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。
类型:
- 代理模式(Proxy)
- 适配器模式(Adapter)
- 桥接模式(Bridge)
- 组合模式(Composite)
- 装饰模式(Decorator)
- 外观模式(Facade)
- 享元模式(Flyweight)
代理模式
代理模式的结构简单,主要定义一个继承抽象主题的代理来包含真实主题,实现对真实主题的访问。
角色:
- 抽象主题类:通过接口或抽象类声明真实主题和代理对象实现业务方法。
- 真实主题类:实现抽象主题中的具体业务,是代理对象所代表的真实对象,是
- 代理类:提供了真实主题相同接口,其内部含有对真实主题的引入,可以访问,控制或扩展真实的功能。
代理模式的结构图:
适配器模式
定义
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
出现两个对象因接口不兼容而不能在一起工作,需第三者适配。
tip:在软件设计中也可能出现:需要开发的具有某种业务功能的组件在现有的组件库中已经存在,但它们与当前系统的接口规范不兼容,如果重新开发这些组件成本又很高,这时用适配器模式能很好地解决这些问题。适配器模式分为(类结构型模式)和(对象结构型模式)两种。
优点
- 客户端通过适配器可以透明地调用目标接口。
- 复用了现存的类,程序员不需要修改原有代码而重用现有的适配者类。
- 将目标类和适配者类解耦,解决了目标类和适配者类接口不一致的问题。
缺点
对类适配器来说,更换适配器的实现过程比较复杂。
类适配器模式可采用多重继承方式实现
如 C++ 可定义一个适配器类来同时继承当前系统的业务接口和现有组件库中已经存在的组件接口;
Java 不支持多继承,但可以定义一个适配器类来实现当前系统的业务接口,同时又继承现有组件库中已经存在的组件。
模式的结构
适配器模式包含以下主要角色。
- 目标接口:当前系统业务所期待的接口,它可以是抽象类或接口。
- 适配者类:它是被访问和适配的现存组件库中的组件接口。
- 适配器类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。
桥接模式
在现实生活中,某些类具有两个或多个维度的变化,如图形既可按形状分,又可按颜色分。如何设计类似于 Photoshop 这样的软件,能画不同形状和不同颜色的图形呢?如果用继承方式,m 种形状和 n 种颜色的图形就有 m×n 种,不但对应的子类很多,而且扩展困难。
定义
将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度。
优点
由于抽象与实现分离,所以扩展能力强; 其实现细节对客户透明。
缺点
由于聚合关系建立在抽象层,要求开发者针对抽象化进行设计与编程,这增加了系统的理解与设计难度。
桥接模式的结构与实现
可以将抽象化部分与实现化部分分开,取消二者的继承关系,改用组合关系
模式的结构
- 抽象化角色:定义抽象类,并包含一个对实现化对象的引用。
- 扩展抽象化角色:是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
- 实现化角色:定义实现化角色的接口,供扩展抽象化角色调用。
- 具体实现化角色:给出实现化角色接口的具体实现。
结构图
例题:
用桥接(Bridge)模式模拟女士皮包的选购。
分析:女士皮包有很多种,可以按用途分、按皮质分、按品牌分、按颜色分、按大小分等,存在多个维度的变化,所以采用桥接模式来实现女士皮包的选购比较合适。
组合模式
组合模式分为(透明式的组合模式)和(安全式的组合模式)。
在现实生活中,存在很多“部分-整体”的关系,例如,大学中的部门与学院、总公司中的部门与分公司。在软件开发中也是这样,例如,文件系统中的文件与文件夹、窗体程序中的简单控件与容器控件等。对这些简单对象与复合对象的处理,如果用组合模式来实现会很方便。
定义
有时又叫作部分-整体模式,它是一种将对象组合成树状的层次结构的模式,用来表示“部分-整体”的关系,使用户对单个对象和组合对象具有一致的访问性。
优点
- 组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码;
- 更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”;
缺点
- 设计较复杂,客户端需要花更多时间理清类之间的层次关系;
- 不容易限制容器中的构件;
- 不容易用继承的方法来增加构件的新功能;
应用场景
- 在需要表示一个对象整体与部分的层次结构的场合。
- 要求对用户隐藏组合对象与单个对象的不同,用户可以用统一的接口使用组合结构中的所有对象的场合。
模式的结构
- 抽象构件角色:它的主要作用是为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。在透明式的组合模式中抽象构件还声明访问和管理子类的接口;在安全式的组合模式中不声明访问和管理子类的接口,管理工作由树枝构件完成。
- 树叶构件角色:是组合中的叶节点对象,它没有子节点,用于实现抽象构件角色中 声明的公共接口。
- 树枝构件角色:是组合中的分支节点对象,它有子节点。它实现了抽象构件角色中声明的接口,它的主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。
(1)透明模式
在该方式中,由于抽象构件声明了所有子类中的全部方法,所以客户端无须区别树叶对象和树枝对象,对客户端来说是透明的。但其缺点是:树叶构件本来没有 Add()、Remove() 及 GetChild() 方法,却要实现它们(空实现或抛异常),这样会带来一些安全性问题。
结构图
(2)安全方式
在该方式中,将管理子构件的方法移到树枝构件中,抽象构件和树叶构件没有对子对象的管理方法,这样就避免了上一种方式的安全性问题,但由于叶子和分支有不同的接口,客户端在调用时要知道树叶对象和树枝对象的存在,所以失去了透明性。
结构图
实例
【例1】用组合模式实现当用户在商店购物后,显示其所选商品信息,并计算所选商品总价的功能。 说明:假如李先生到哈尔滨“远大”购物中心购物,用 1 个红色小袋子装了 2 包哈尔滨特产(单价 7.9 元)、1 张哈尔滨地图(单价 9.9 元);用 1 个白色小袋子装了 2 袋秋林红肠(单价 68 元)和 3 包红茶(单价 180 元);用 1 个中袋子装了前面的红色小袋子和 1 个索菲亚教堂(单价 380 元);用 1 个大袋子装了前面的中袋子、白色小袋子和 1 双李宁牌运动鞋(单价 198 元)。 最后“大袋子”中的内容有:{1 双李宁牌运动鞋(单价 198 元)、白色小袋子{2 袋秋林红肠(单价 68 元)、3 包红茶(单价 180 元)}、中袋子{1 个索菲亚教堂(单价 380 元)、红色小袋子{2 包哈尔滨特产(单价 7.9 元)、1 张哈尔滨地图(单价 9.9 元)}}},现在要求编程显示李先生放在大袋子中的所有商品信息并计算要支付的总价。
装饰模式
定义
指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。
优点
- 采用装饰模式扩展对象的功能比采用继承方式更加灵活。
- 可以设计出多个不同的具体装饰类,创造出多个不同行为的组合。
缺点
装饰模式增加了许多子类,如果过度使用会使程序变得很复杂。
模式的结构
- 抽象构件角色:定义一个抽象接口以规范准备接收附加责任的对象。
- 具体构件角色:实现抽象构件,通过装饰角色为其添加一些职责。
- 抽象装饰角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
- 具体装饰角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。
结构图
实例
用装饰模式实现游戏角色“莫莉卡·安斯兰”的变身。
分析:在《恶魔战士》中,游戏角色“莫莉卡·安斯兰”的原身是一个可爱少女,但当她变身时,会变成头顶及背部延伸出蝙蝠状飞翼的女妖,当然她还可以变为穿着漂亮外衣的少女。这些都可用装饰模式来实现,在本实例中的“莫莉卡”原身有 setImage(String t) 方法决定其显示方式,而其 变身“蝙蝠状女妖”和“着装少女”可以用 setChanger() 方法来改变其外观,原身与变身后的效果用 display() 方法来显示
外观模式
在现实生活中,常常存在办事较复杂的例子,如办房产证或注册一家公司,有时要同多个部门联系,这时要是有一个综合部门能解决一切手续问题就好了。
软件设计也是这样,当一个系统的功能越来越强,子系统会越来越多,客户对系统的访问也变得越来越复杂。这时如果系统内部发生改变,客户端也要跟着改变,这违背了“开闭原则”,也违背了“迪米特法则”,所以有必要为多个子系统提供一个统一的接口,从而降低系统的耦合度,这就是外观模式的目标。
定义
是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更加容易被访问的模式。 该模式对外有一个统一接口,外部应用程序不用关心内部子系统的具体的细节,这样会大大降低应用程序的复杂度,提高了程序的可维护性。
外观模式的结构与实现
外观(Facade)模式的结构比较简单,主要是定义了一个高层接口。它包含了对各个子系统的引用,客户端可以通过它访问各个子系统的功能。
模式的结构
- 外观(Facade)角色:为多个子系统对外提供一个共同的接口。
- 子系统(Sub System)角色:实现系统的部分功能,客户可以通过外观角色访问它。
- 客户(Client)角色:通过一个外观角色访问各个子系统的功能。
外观模式的扩展
在外观模式中,当增加或移除子系统时需要修改外观类,这违背了“开闭原则”。如果引入抽象外观类,则在一定程度上解决了该问题。
优点
- 降低了子系统与客户端之间的耦合度,使得子系统的变化不会影响调用它的客户类。
- 对客户屏蔽了子系统组件,减少了客户处理的对象数目,并使得子系统使用起来更加容易。
- 降低了大型软件系统中的编译依赖性,简化了系统在不同平台之间的移植过程,因为编译一个子系统不会影响其他的子系统,也不会影响外观对象。
缺点
- 不能很好地限制客户使用子系统类。
- 增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”。
享元模式Flyweight(对象类,网站共享、围棋)
动机
如一个软件系统在运行时所创建的相同或相似对象数量太多,将导致运行代价过高,带来系统资源浪费、性能下降等问题
如何避免系统中出现大量相同或相似的对象,同时又不影响客户端程序通过面向对象的方式对这些对象进行操作呢? 运用共享技术有效地支持大量细粒度的对象。
适用性
- 一个系统有大量的对象。
- 这些对象耗费大量的内存。
- 这些对象的状态中的大部分都可以外部化。
- 这些对象可以按照内部状态分成很多的组,当把外部对象从对象中剔除时,每一个组都可以仅用一个对象代替。
分析
内部状态(Intrinsic State):存储在享元对象内部并且不会随环境改变而改变的状态,内部状态可以共享(例如:字符的内容)
外部状态(Extrinsic State):随环境改变而改变的、不可以共享的状态。享元对象的外部状态通常由客户端保存,并在享元对象被创建之后,需要使用的时候再传入到享元对象内部。一个外部状态与另一个外部状态之间是相互独立的(例如:字符的颜色和大小)
原理
- (1) 将具有相同内部状态的对象存储在享元池中,享元池中的对象是可以实现共享的
- (2) 需要的时候将对象从享元池中取出,即可实现对象的复用
- (3) 通过向取出的对象注入不同的外部状态,可以得到一系列相似的对象,而这些对象在内存中实际上只存储一份
行为者模式
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。
行为型模式分为(类行为模式)和(对象行为模式),前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。
- 模板方法模式:定义一个操作中的算法骨架,将算法的一些步骤延迟到子类中,使得子类在可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
- 策略模式:定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的改变不会影响使用算法的客户。
- 命令模式:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。
- 职责链模式:把请求从链中的一个对象传到下一个对象,直到请求被响应为止。通过这种方式去除对象之间的耦合。
- 状态模式:允许一个对象在其内部状态发生改变时改变其行为能力。
- 观察者模式:多个对象间存在一对多关系,当一个对象发生改变时,把这种改变通知给其他多个对象,从而影响其他对象的行为。
- 中介者模式:定义一个中介对象来简化原有对象之间的交互关系,降低系统中对象间的耦合度,使原有对象之间不必相互了解。
- 迭代器模式:提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。
- 访问者模式:在不改变集合元素的前提下,为一个集合中的每个元素提供多种访问方式,即每个元素有多个访问者对象访问。
- 备忘录模式:在不破坏封装性的前提下,获取并保存一个对象的内部状态,以便以后恢复它。
- 解释器模式:提供如何定义语言的文法,以及对语言句子的解释方法,即解释器。
以上 11 种行为型模式,除了模板方法模式和解释器模式是类行为型模式,其他的全部属于对象行为型模式.
模板方法模式
定义
定义一个操作中的算法骨架,将算法的一些步骤延迟到子类中,使得子类在可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
组成
抽象父类:定义并实现了模板方法,定义了算法的骨架。抽象操作
具体类:实现抽象类中的抽象方法,即不同的对象的具体实现细节。
- (1)抽象类(Abstract Class):负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。这些方法的定义如下。
- ① 模板方法:定义了算法的骨架,按某种顺序调用其包含的基本方法。
- ② 基本方法:是整个算法中的一个步骤,包含以下几种类型。抽象方法:在抽象类中申明,由具体子类实现。
- 具体方法:在抽象类中已经实现,在具体子类中可以继承或重写它。
- 钩子方法:在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种。
- (2) 具体子类(Concrete Class):实现抽象类中所定义的抽象方法和钩子方法,它们是一个顶级逻辑的一个组成步骤。
优点
- 它封装了不变部分,扩展可变部分。它把认为是不变部分的算法封装到父类中实现,而把可变部分算法由子类继承实现,便于子类继续扩展。
- 它在父类中提取了公共的部分代码,便于代码复用。
- 部分方法是由子类实现的,因此子类可以通过扩展方式增加相应的功能,符合开闭原则。
缺点
- 对每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象。
- 父类中的抽象方法由子类实现,子类执行的结果会影响父类的结果,这导致一种反向的控制结构,它提高了代码阅读的难度。
模式扩展
在模板方法模式中,基本方法包含:抽象方法、具体方法和钩子方法,正确使用“钩子方法”可以使得子类控制父类的行为。
钩子方法
对于抽象方法或者接口中定义的方法的一个空实现,比如说有一个接口,这个接口中定义了很多个方法,而你想实现其中某一个方法,这个时候就可以写一个抽象类实现这个接口,在这个抽象类里将你要用的那个方法设置为abstract,其它方法进行空实现,然后再继承这个抽象类,就不需要实现其它不用的方法,这就是钩子方法的作用。
含钩子方法的模板方法模式的结构图
策略模式
现实生活中常常遇到实现某种目标存在多种策略可供选择的情况,例如,出行旅游可以乘坐飞机、乘坐火车、骑自行车或自己开私家车等。 在软件开发中也常常遇到类似的情况,当实现某一个功能存在多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能,如数据排序策略有冒泡排序、选择排序、插入排序、二叉树排序等。
定义
该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。
定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化
- 环境(Context)角色:持有一个Strategy类的引用。
- 抽象策略(Strategy):一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
- 具体策略(ConcreteStrategy):包装了相关的算法或行为。
步骤
- 1、定义抽象角色类,定义好各个实现的共同抽象方法;
- 2、定义具体策略类,具体实现父类的共同方法;
- 3、定义环境角色类,私有化申明抽象角色变量,重载构造方法,执行抽象方法。
适用性
- 1、 多个类只区别在表现行为不同,可使用Strategy模式,在运行时动态让对象选择具体要执行的一种行为。
- 2、 要在不同情况下使用不同的策略(算法),动态的选择一种算法,或者策略还可能在未来用其它方式来实现。
- 3、 对客户隐藏具体策略(算法)的实现细节或算法使用的数据,彼此完全独立。
优点
- 1、 提供了一种替代继承的方法,保持继承的优点,比继承更灵活
- 2、 避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。
- 3、提供了管理相关的算法族的方法,使这些算法可以相互替换,自由切换。
- 4、 遵守大部分原则。
- 5、 简化了单元测试,因每个算法都有自己的类,可以通过自己的接口单独测试。
缺点
- (1)所有的策略模式都需要对外暴露 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
- (2)造成很多的策略类
- (3)只适合扁平的算法结构,不适合于处理同时嵌套多于一个算法的情形。
状态模式
定义
一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。抽 行为 封装
- 抽象状态(State)角色:定义接口,用以封装环境(Context)对象的一个特定的状态所对应的行为。
- 具体状态(Concrete State):每个具体状态类都实现了环境(Context)的一个状态所对应的行为。
- 环境(Context)角色:定义客户端感兴趣的接口,并保留一个具体状态类的实例。这个具体类的实例给出此环。
适用
- 一个对象的行为依赖于它所处的状态(如某些属性值),对象的行为必随其状态的改变而改变
- 对象在某个方法里依赖于一重或多重的条件转移语句,其中有大量的代码,灵活性,维护性差,增删状态不方便
优点
- 1、封装了转换规则。
- 2、枚举可能的状态,在枚举状态之前需要确定状态种类。
- 3、将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
- 4、允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
- 5、可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
缺点
- (1)类和对象的个数多。
- (2)复杂,结构和代码可能混乱,设计难。
命令模式
将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化;对请求 排队或 记录请求日志,以及支持可撤销的操作.是对象行为型模式,别名为动作(Action)模式或事务(Transaction)模式。
- Command: 抽象命令类
- ConcreteCommand: 具体命令类
- Invoker: 调用者 Receiver: 接收者
- Client:客户类
优点
- 降低系统耦合度。
- 新命令可很容易加入到系统中
- 较易设计一个命令队列和宏命令(组合命令)。
- 可方便地实现对请求的Undo和Redo。
缺点
导致某些系统有过多的具体命令类。因为针对每个命令都需要设计一个具体命令类,大量具体命令类,影响模式的使用。
适用性
- 系统要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
- 系统要在不同的时间指定请求、将请求排队和执行请求。
- 系统要支持命令的撤销(Undo)操作和恢复(Redo)操作。
- 系统要将一组操作组合在一起,即支持宏命令。
观察者模式
定义
对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
关键代码:在抽象类里有一个 ArrayList 存放观察者们。
应用实例:
1、拍卖的时候,拍卖师观察最高标价,然后通知给其他竞价者竞价。
2. 医学影像三维重建完成后,发通知给医生和患者查看结果。
优点
- 1、观察者和被观察者是抽象耦合的。
- 2、建立一套触发机制。
缺点
- 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
- 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
- 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
适用场景
- 【1】一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
- 【2】一个对象必须通知其他对象,而并不知道这些对象是谁。
- 【3】需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。
实现
ObserverPatternDemo,使用 Subject 和实体类对象来演示观察者模式。
访问者模式
定义
表示一个作用于某对象结构中的各元素的操作。它可在不改变各元素的类的前提下定义 作用于这些元素的新操作
tip: 使用这个模式后可在不修改已有程序结构的前提下,通过添加额外的“访问者”完成对已有代码功能的提升。
实例
适用
- 1 一个对象结构包含很多类对象,它们有不同的接口,想对这些对象实施一些依赖于其具体类的操作。
- 2 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而想避免让这些操作“污染”这些对象的类。
- 3 对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作
优点
- 1、增加新的访问操作很方便
- 2、将有关元素对象的访问行为集中到一个访问者对象中,而不是分散在一个个的元素类中,类的职责更加清晰
- 3、让用户能够在不修改现有元素类层次结构的情况下,定义作用于该层次结构的操作。
缺点
增加新的元素类很困难 破坏封装
职责链模式
定义
很多对象由每一个对象对其下家的引用而联接起来形成一条链。请求在这个链上传递,直到链上的某个对象决定处理此请求。发出这个请求的客户端不知道链上的哪个对象最终处理这个请求。责任链可能是一条直线、一个环链甚至一个树结构的一部分。
- 抽象处理者(Handler):定义出一个处理请求的接口。如需要,接口可定义 出一个方法以设定和返回对下家的引用。通常由1个Java抽象类或接口实现。Handler类的聚合关系给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作。
- 具体处理者(ConcreteHandler):它接到请求后,可选择将请求处理掉,或将请求传给下家。由于具体处理者持有对下家的引用,如需要,它可访问下家。
实例
优点
- 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。
- 增强了给对象分配响应(职责)的灵活性。
适用性
有多个对象可处理一个请求,哪个对象处理该请求在运行时刻自动确定。 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求。
迭代模式
定义
提供一种方法顺序访问一个聚合对象中各个元素, 又不暴露该对象的内部结构和表示。又叫Cursor游标模式、迭代子模式
- 抽象容器:一般是个接口,提供一个iterator()方法
- 具体容器:抽象容器的具体实现类。
- 抽象迭代器:定义访问和遍历元素的接口和所需要的方法
- 迭代器实现:实现迭代器接口中定义的方法,完成集合的迭代。记录遍历中的当前位置
目的
- 一个聚合对象,如一个列表(List)或者一个集合(Set),应提供一种方法让别人可以访问(遍历)它的元素,而又不需要暴露它的内部结构。
- 针对不同需要,可能还要以不同的方式遍历整个聚合对象,但不希望在聚合对象的抽象层接口中充斥着各种不同遍历的操作。
- 提供一个外部的迭代器来对聚合对象进行访问和遍历,迭代器定义了一个访问该聚合元素的接口,且可跟踪当前遍历的元素,了解哪些元素已经遍历过而哪些没有。
- 有该模式,发现对一个复杂的聚合对象的操作变简单。
分析
聚集对象的职责:
- 存内部数据,聚合对象的基本职责
- 遍历内部数据,既是可变化的,又是可分离的
聚集是一个管理和组织数据对象的数据结构。
将遍历数据的行为从聚合对象中分离出来,封装在迭代器对象中。
本质:由迭代器来提供遍历聚合对象内部数据的行为,简化聚合对象的设计符合单一职责原则,是其完美体现
优点
- 支持以不同的方式遍历一个聚合对象。
- 算法独立与聚集的变化,支持遍历不同的聚集对象。
- 迭代器简化了聚合类(聚集对象接口),聚集对象不必具备便利接口。
- 在同一个聚合上可以有多个遍历,多个不同的迭代器,定义多种遍历方式。 因引入了抽象层,增加新的聚合类和迭代器类都很方便,无须修改原有代码。
- 引入迭代器,客户端无须了解聚合对象的内部结构即可实现对聚合对象中成员的遍历,还可以根据需要很方便地增加新的遍历方式
缺点
将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,一定程度上增加了系统的复杂性。
抽象迭代器的设计难度大,要充分考虑到系统将来的扩展。在自定义迭代器时,创建一个考虑全面的抽象迭代器并不是一件很容易的事情
实例
适用
为遍历不同的聚合结构提供一个统一的接口。
中介调停者模式
定义
用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
组合
- 抽象调停者(Mediator)角色:定义出同事对象到调停者对象的接口,其中主要方法是一个(或多个)事件方法。
- 具体调停者(ConcreteMediator)角色:实现了抽象调停者所声明的事件方法。具体调停者知晓所有的具体同事类,并负责具体的协调各同事对象的交互关系。
- 抽象同事类(Colleague)角色:定义出调停者到同事对象的接口。同事对象只知道调停者而不知道其余的同事对象。
- 具体同事类(ConcreteColleague)角色:所有的具体同事类均从抽象同事类继承而来。实现自己的业务,在需要与其他同事通信的时候,就与持有的调停者通信,调停者会负责与其他的同事交互
适用性
- 一组对象以定义良好但是复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解。
- 一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象。
- 想定制一个分布在多个类中的行为,而又不想生成太多的子类。
解释器
定义
给定一个语言, 定义它的文法的一种表示,并定义一个解释器, 该解释器使用该表示来解释语言中的句子。
组成
Context 解释器上下文环境类。存储解释器的上下文环境,如需要解释的文法等
AbstractExpression 解释器抽象类。
ConcreteExpression 解释器具体实现类。
适用
有一个简单的语法规则,根据需要进行转换, 一些重复发生的问题,比如加减乘除四则运算
优点
解释器是一个简单的语法分析工具,扩展性好,修改语法规则只需要修改相应的 非终结符 就可以了,若扩展语法,只需要增加非终结符类就可以了。
缺点
类膨胀,解析复杂问题效率低
备忘录模式
定义
保存一个对象的某个状态(快照),以便在适当的时候恢复对象。又叫 快照模式或Token模式。
实现方式
白箱实现,黑箱实现。
白箱实现
备忘录角色的内部所存储的状态对所有对象公开。将发起人角色的状态存储在大家看得到的地方,因此是破坏封装性的。但通过程序员自律,可在一定程度上实现模式的大部分用意。因此仍有意义。
宽窄接口:双重接口,就是对某一个对象提供宽接口,而对另一些对象提供窄接口。根据编程语言的性能,双重接口的实现方式有所不同
黑河实现
Java可将备忘录角色(Memento)设成发起人角色(Originator)的内部类,即将备忘录对象封装在发起人角色里;在外部提供1个标识接口(MementoIF)给负责人(Caretaker)及其它对象。这样发起人看到 的是备忘录的所有接口,而负责人及其它对象看到的仅仅是标识接口。
白箱和黑箱的示意性实现都是只存储一个状态的简单实现。常见的系统要存储不只一个状态,要存储多个状态,或叫多个检查点。 发起人角色的状态存储在Vector对象中,每个状态都有一个对应的索引号index
优点
- 用备忘录 保存对象的历史状态可有效地保持封装边界。
- 简化了发起人(Originator)类。发起人不再需要管理和保存其内部状态的一个个版本,客户端可自行管理它们所需要的这些状态的版本。
- 当发起人状态需要复原时,可用存储起来的备忘录将状态恢复。
缺点
开销大
适用
遇到要恢复状态的问题
题目
- 软件可行性研究一般不考虑 待开发的软件是否会有质量问题
- 可行性研究要进行一次何种程度的需求分析? 简化的、压缩了的
- 成本---效益分析可用哪些指标进行度量?
有形效益度量:
a.货币的时间价值
b.投资回收期
c.纯收入
无形效益:主要从性质上、心理上进行衡量,很难直接进行量的比较。
通常以有形效益度量作为成本---效益分析的度量。
-
可行性研究有哪些步骤?
a.确定项目规模和目标
b.研究正在运行的系统
c.建立新系统的高层逻辑模型
d.导出和评价各种方案
e.推荐可行的方案
f.编写可行性研究报告
-
可行性研究的任务是什么?
a.技术可行性:
考虑的因素(1).开发的风险(2)资源的有效性(3)技术(4)开发人员在主段技术可行性时,一旦估计错误,将会出现灾难性后果。
b.经济可行性。
c.社会可行性。
-
CMM模型是软件成熟度模型的简称
-
CMM模型中已定义级是第三级
-
CMM模型中能体现定量管理,组织可度量的质量和生成目标的是第4级
-
CMM模型中能体现发现问题解决问题,持续改进,发动革命的是第5级
-
CMM模型中,建立项目纪律,形成尊重质量的纪律文化,认识到流程的重要性。使得流程得到遵守的,可重复的是第2级
-
CMM中,系统开发项目没有规定的过程可以遵循的是第1级
-
BSP又称为企业系统规划法
-
战略集合转移法要和 组织的战略目标 相匹配
-
关键成功因素法称为CSF
-
CSF方法要求识别所有的成功因素,再确定关键的成功因素
-
关键成功因素法主要用到的工具是 鱼骨图
-
核心突出型 不是鱼骨图的类型
-
企业系统规划法采用自上而下的分析,核心步骤是定义企业目标,定义企业过程,定义数据类,定义系统目标
-
因为数据类当中的功能主要确定 画出过程的输入输出图
-
规划方法中主要包含 战略集合转换法, 关键成功因素法,企业系统规划法,价值链分析法
-
企业系统规划法出发点:系统必要支持企业目标,系统战略表达企业各个管理层要求,应再组织机构和管理机制改变时保存工作能力,系统战略规划应由总体系统中的子系统开始实现
-
需求分析最终结果是产生需求规格说明书
-
需求分析的根本任务包括 建立分析模型 建立解决方案
-
优秀需求的特性 完整性,正确性,可行性,必要性,无歧义,可验证
-
非功能需求包括 性能需求 质量属性 对外接口 约束条件
-
严格意义上需求分析包括 功能需求和非功能需求
-
需求的三个层次包括 业务需求 用户需求 系统需求
-
需求的三个层次对应的文档为 项目前景和范围文档 用例文档 软件需求规格说明
-
需求工程的主要活动包括需求开发和需求管理,其中,需求开发包括 需求获取,需求分析 需求规格说明 需求验证
-
-
-
-
-
系统流程图中指定的关键字以升序或降序改变源文件的记录排列顺序,这叫 分类
-
习通流程图的基本处理工序为变换,合并,划分,排序,更新
-
系统流程图中,划分是合并的逆操作,即将合并工序的输入文件与输出文件对调
-
结构化分析方法中,数据流图的基本成分为 源点,数据存储,处理,数据流
-
画DFD图的主要目的是 作为需求分析阶段用户与开发者之间交流的工具 作为分析和设计的工具
-
画分层DFD图的基本原则是 数据流封闭的原则 数据守恒原则 子、父图平衡的原则
-
SA法是面向数据流,建立在数据封闭原则上的需求分析方法。
-
数据字典是数据流图中所有元素的定义的集合,一般由:数据项条目,数据流条目,数据处理条目,数据文件存储条目
-
数据流图是进行软件需求分析的常用图形工具,其基本图形符号是
加工、数据流、数据存储、外部实体
-
以下哪个不是画分层DFD图的基本原则 分解的可靠性原则
- UML中5大视图包括 用例视图、 逻辑视图、构件视图、进程视图和配置视图
- 用例描述中,事件流包括 基本事件流和 备选事件流,可以完整描述一个基本的用例场景。
- UML以 用例 驱动的,以体系结构为中心的,迭代和增量的软件过程。
- 执行者(Actor)与用例之间的关系是 关联关系
- 用例之间的关系有 组合,适用,扩展
- 用例场景包括 后备事件流,主事件流
- 包含用例是一个完整的用例,它可以独立的存在,也可以单独被执行者所调用。扩展用例并不是一个完整的用例,不能独立的存在,必须依赖于基本用例。
- UML总体上主要分为两类图,即静态图、动态图
- 在系统之外,透过系统边界与系统进行有意义交互的任何事物,称为 参与者
- 属于Coad方法中面向对象的分析模型的层次有 对象层,主题层
- 事件流包括 扩展事件流,基本事件流
- UML的元素之间的关系包括 实现,关联,泛化,依赖
- UML的三大种图: 静态模型图(对象模型) 用例模型图(功能模型) 动态模型图(行为模型)
- 依赖关系包括 包含依赖 扩展依赖
- 微服务开发特性: 可独立部署,松耦合,能部署和运行小产品,可并行开发
- 微服务拥有 粒度小,服务间全解耦,轻量级机制,单独的进程
- 微服务架构由一系列小服务组成,每个服务运行于自己的独立进程,围绕业务功能进行建模。每个服务可进行独立部署。
- 微服务有着 去中心化 的服务架构和嵌入式系统的 组件 化架构
- 需求验证的方法包括 利用跟踪关系 开发测试用例,原型与模拟,审评
- 需求管理的活动包括 维护需求基线,实现需求跟踪,控制变更
- 缺陷修复是最为频繁的变更类型
- 新增需求是影响最大的变更类型
- 属于面向对象的要素的是 继承,抽象,封装
- 面向对象程序设计的基本机制:继承,消息,方法
- UML关系包括 泛化,聚合,依赖,组合
- UML语言支持的建模方式 静态建模,动态建模,功能性建模
- 状态图不是UML中的静态视图
- 类的识别方法包括 名词识别法 从用例中识别类 实体(ERD)-对象法(ORD) 使用类-职责—协作卡(CRC卡)的方法
- 类的三个抽象层次 概念层,说明层,实现层
- UML的类图包含哪些抽象的层次 概念层,说明层,业务层
- 面向对象的要素:抽象,继承,封装
- 类的设计过程确定类,确定关联类,确定属性,识别继承关系。
- 定义属性,包括定义类的实例 对象 之间的实例连接。
- 属性的可见性有 共有的,私有的,保护的
- 一个属性依其特征,其类型有 描述型,定义型,派生型
- 互斥属性的解决办法一般是 多重继承
- 类的操作可以有以下: 参数表,可见性,操作名,返回类型,特征描述
- 下面对类图和对象描述正确的是 类通常具有三个分栏:名称、属性和操作 对象名称形式为“对象名:类名”,匿名对象名称形式为“:类名”;有下划线 类之间的关系可以使用多重性 对象使用链连接,链拥有名称、角色,但是没有多重性
- 包之间有 依赖 和 继承 两种关系
- UML具有扩展性,常见的扩展机制有 版类,加标签值,约束
- 消息的类型: 同步,异步,简单
- 消息的主要任务:对象间发送信号,创建目标对象,对象间调用操作,撤销目标对象
- 接收者对消息的不同响应方式
-
在消息产生之前,处理这个消息的控制流并不存在,仅当发送者发出这个消息时,才立刻创建一个控制流来响应这个消息,完成他要求的操作 内部消息不需要表示 某些消息所指出的接收者,可能并不关心这种消息,也不做任何回应
-
中介者不是消息的组成部分
-
特征描述不是消息的内容标识
-
顺序系统中没有异步消息
-
并发系统包含异步也包含同步消息
-
并发系统中,同步消息分为阻断和限时
-
顺序系统中的消息并不都是同步的,并发系统都是有多个主动对象的。(×)
-
动态建模:状态图,序列图,活动图
-
时序图的用途:A、显示并发进程和激活B、当不同的类之间存在多个简短的方法时,描述控制流的整体序列C、显示在协作图中难于描述的事件序列D、显示涉及类交互而与对象无关的一般形式
-
顺序图的用途包括 A、显示并发进程和激活 B、当不同的类之间存在多个简短的方法时,描述控制流的整体序列 C、显示在协作图中难于描述的事件序列 D、显示涉及类交互而与对象无关的一般形式
-
协作图不是顺序图的一种特例
-
部署图中的节点:计算能力,基本内存,位置
-
组件,关系,接口构成组件图形
-
根据设计模式思想程序开发中应该优先使用( )关系实现复用 组合
-
依赖倒置原则就是要依赖于( ),或者说针对接口编程,不要针对实现编程。 抽象
-
面向对象设计原则中最核心的原则是 开闭原则
-
依赖倒置原则是指高层模块应该依赖于底层模块,两者都依赖于具体的实现 (×)
-
开闭原则是指一个软件实体应当对 扩展 开放,对 修改 关闭。
-
观察者模式是行为模式
-
创建一个具体的对象而又不希望指定具体的类时,可以使用()模式 创建型
-
设计模式具有的优点 适应需求变化
-
常用的设计模式分为 创建型 结构型和行为型
-
程序开发优先使用 组合聚合和继承 关系实现复用
-
设计模式一般用来解决 同一问题的不同表相 问题
-
设计模式的基本要素 名字,解决方案,问题,意图
-
大多数设计模式可以让软件更具有可修改性
-
适配器模式属于创建型模式(×)
-
抽象工厂模式属于 创建型模式
-
创建型模式 关注的是对象创建
-
简单工程模式中,需要增加新的具体产品,通常需要修改 工厂类 的源代码
-
两者都满足开闭原则:简单工厂以if else 方式创建对象,增加需求看看 时候会修改源代码(×)
-
适配器模式 不属于创建型模式
-
简单工厂模式核心是 简单工厂
-
工厂方式模式的核心是 一个抽象工厂
-
两者都完美满足开闭原则,简单工厂以if else方式创建对象,增加需求的时候会修改源代码(×)
-
Strategy(策略)模式的意图是
定义一系列的算法,把它们一个个的封装起来,并且使它们可相互替换
-
观察者模式属于行为模式
-
系统有用户信息操作模块,用户能修改自己的各项信息。为了使操作更人性化,可使用( )对系统改进,使用户在进行错误操作后可恢复到操作前的状态。 备忘录模式
-
当我们想封装不同算法并使它们可以相互替换时,可以使用()
策略模式
-
策略模式还简化了单元测试,每个算法都有自己的类,可以通过自己的()单独测试。 接口
-
()模式描述了如何为简单的语言定义一个文法,如何在该语言中表示一个句子,以及如何解释这些句子 解释器
-
策略模式的结构中包括三种角色()、具体策略和抽象策略。
上下文环境