面向对象分析与设计知识总结
考试内容
%50 教材涉及的基本概念
15% 根据业务需求设计简单的静态概念模型或静态设计模型
15% 重构
20% 设计模式
设计模式考试范围
策略模式(Strategy)
观察者模式(Observer)
具体工厂模式(Concrete Factory)
单实例模式(Singleton)
-
迭代器模式(Iterator)
-
装饰器模式(Decorator)
-
组合模式(Composite)
其中打星号的为补充的内容
PPT知识点(书中无对应点)
Chapter2.5 面向对象介绍
- 纯面向对象的编程语言并不能保证写出面向对象风格的程序,关键点在于程序的编写者是否符合面向对象的编程范式
- 使用延迟绑定的机制实现多态
- 每当你发现自己是通过查看了的内部实现来得知该如何使用这个类的时候,你就不是在针对接口编程了
Chapter22.1 测试驱动开发
- 传统测试方法及问题
- 测试往往不够完整,会导致遗漏错误
- 测试往往由专门的测试人员实施,他们对程序的细节往往不够熟悉
- 测试人员通常根据文档,而不是代码来觉得究竟要测试哪些内容,而这些文档很容易过期而与代码不一致
- 大多数的测试是基于手工的,不能够自动完成,因此无法经常执行
- 什么是测试驱动开发?
- 先写单元测试用例,再写代码
- 由测试来决定需要什么样的代码
- 由程序员编写和维护完整的测试用例集
- 仅当代码有了相应的测试代码,该代码才能作为成品代码
- 测试驱动开发的优点
- 能够保证编写单元测试
- 使得程序员获得满足感,从而始终如一地坚持编写测试
- 有助于澄清接口和行为的细节
- 可证明、可再现、可自动验证
- 改变事物的信心
- 编写测试用例时的几点注意事项
- 使用setup()和tearDown()来创建、初始化和释放测试用例之间公共的测试对象及所需的环境
- 确保测试没有副作用
- 确保测试用例之间没有依赖关系
- Mock对象的优缺点
- 优点:不需要运行的容器来执行测试
- 缺点:没有测试容器和组件之间的交互、没有测试组件的部署部分、需要对调用的API有很好的了解才能模拟它(这可能很困难)
Chapter21.2重构
- 布局和风格(Layout and Style)
- 良好的可视化布局显示程序的逻辑结构
- 编程工作的一小部分内容是让机器理解代码,大部分内容是让其他人能够读懂代码
- 良好布局的目标:准确表达代码的逻辑结构、一致地表示代码的逻辑结构、提高可读性、经得起修改
-
布局技术:空白符、括号、使用其他工具
-
Self-Documenting Code
- Programming Style as Documentation:代码级文档的主要贡献者不是注释,而是良好的编程风格,这些风格包括——良好的程序结构、变量命名、清晰的布局、使用命名的常量而不是字面量。
- To Comment or Not to Comment:注释应当是对代码的总结、对代码意图的描述、代码本身无法表达的信息,避免对重复代码、对代码进行解释、在代码中做标记。注释的最佳数量:每10条语句一条注释,注释过少会让代码难以理解,注释过多会降低代码的可读性。
-
重构
- 软件进化哲学:如果你意识到开发过程中的evolution是一个迭代的、重要的现象并且按照计划执行它,那么你就能从中受益;evolution应当提升程序的内部质量。
- 什么是重构:对软件内部结构所做的一种修改,在不改变软件外部行为的情况下,使得其更容易理解和更便宜地修改。
- 重构的原因(Reasons to Refactor):
- 代码重复
- 方法过长
- 循环太长或者嵌套太深
- 类的内聚度低
- 接口没有提供一致的抽象级别
- 参数列表过长
- 对于一个类的修改往往是分开的(类的内聚度低)
- 改变往往需要并行地对多个类进行修改(这几个类之间的耦合度太高,可以合并为一个类)
- 继承层次结构必须并行修改
- case语句需要并行修改 (继承结构存在问题,需要作出调整)
- 一起使用的数据项没有组织到一个类中
- 一个方法使用其他类的属性比使用其所处类的属性还多
- 基础数据类型被重载
- 一个类没有做太多的任务
- 一个类和另一个类过于亲密
- 函数命名太差
- 数据成员是public
- 子类只使用父类函数的一小部分
- 注释用于解释复杂的代码
- 使用全局变量
- 一个程序包含的代码似乎在某天将被用到
- 安全地重构:开始重构之前保存代码、保持重构的部分尽可能小、一次只做一步重构操作、制作重构列表、频繁进行检查、注意编译器的警告、重新进行测试、添加测试用例、审核改变
迭代器模式(Iterator)
- 动机:像列表这样的聚合对象应该为您提供一种访问其元素而不暴露其内部结构的方法。此外,您可能希望以不同的方式遍历列表,这取决于您想要完成的任务。迭代器模式允许您完成所有这一切。此模式的关键思想是负责访问和遍历列表对象,并将其放入迭代器对象中。
- 目的:提供一种在不公开其底层表示的情况下按顺序访问聚合对象元素的方法。
- 适用性:访问聚合对象的内容而不公开其内部表示;支持聚合对象的多个遍历;提供用于遍历不同聚合结构的统一接口
- 参与者:Iterator、ConcreteIterator、Aggregate、ConcreteAggregate
组合模式(Composite)
- 动机:图形应用程序的用户可以将组件分组以形成更大的组件,而这些组件又可以分组以形成更大的组件,基础对象和容器对象应该共享同一个接口。
- 目的:将对象组合到树结构中以表示部分-整体层次结构。Composite允许客户端统一处理单个对象和对象的组合。
- 适用性:你希望客户端能够忽略对象和单个对象的组合之间的差异。客户端将统一处理组合结构中的所有对象。
- 参与者
- 组件:声明组合中对象的接口,根据需要为所有类通用的接口实现默认行为。
- 叶子:组合中的叶子节点,没有孩子节点,定义组合中基础对象的行为。
- 组合:定义有孩子的组件的行为,存储孩子节点。
- 客户端:通过组件接口操纵组合中的对象。
- attention:叶子和组合均实现组件接口。
知识点速查表
知识点 | 书本页码 |
---|---|
什么是分析和设计? | 5 |
分析和设计的区别 | 5 |
什么是面向对象分析和设计? | 5 |
面向对象分析和面向对象设计的关系 | 5 |
定义领域模型 | 6 |
定义交互图 | 7 |
定义设计类图 | 7 |
什么是UML以及应用UML的三种方式 | 8 |
什么是软件开发过程 | 13 |
什么是迭代开发 | 15 |
迭代时间盒 | 15 \ 17 |
一个为期三周的迭代示例 | 15 |
如何在迭代项目中处理变更 | 16 |
为什么迭代 \ 迭代开发的优点 | 17 |
UP 统一过程 | 14 |
敏捷宣言 | 21 |
敏捷原则 | 21-22 |
敏捷UP(Agile UP) | 23 |
UP的阶段 | 25 |
UP科目 | 25-26 |
判断你是否理解迭代开发或UP | 28-29 |
什么是初始阶段 | 36-37 |
初始阶段的持续时间 | 37 |
初始阶段创建的制品 | 38 |
对于初始阶段的错误理解 | 39 |
什么是需求 | 40 |
如何获取需求 | 40 |
进化式需求和瀑布式需求 | 41 |
需求的分类 | 42 |
UP如何组织需求 | 43 |
什么是用例? | 47 |
用例的定义 | 47 |
用例的三种表示方法 \ 格式 | 49 |
用例编写准则一:以无用户界面约束的风格编写用例 | 61 |
用例编写准则二:编写简洁的用例 | 62 |
用例编写准则三:采用参与者的视角 | 62 |
用例编写准则四:保持黑盒风格 | 62 |
如何发现用例 | 62-63 |
老板测试、EBP测试、规模测试 | 66 |
UML用例图 | 67 |
其他描述需求的方法(UML活动图、特征列表) | 69 |
其他需求制品 | 76 |
补充性规格说明 | 78 |
词汇表 | 87 |
设想 | 82 |
业务规则 | 88 |
迭代一的需求和重点 | 92 |
初始阶段完成的内容有 | 94 |
细化之所在 | 95 |
细化阶段的制品 | 96 |
什么是领域模型 | 100 |
领域模型通过UML表示 | 101 |
领域模型不是软件对象的模型 | 101 |
领域模型不是数据模型 | 102 |
如何创建领域模型 | 104 |
概念类及其表示法 | 102 |
找到概念类的三条策略 | 104 |
通过识别名词短语寻找概念类 | 105 |
寻找和描绘概念类的几个准则 | 107-108 |
不使用描述类存在的问题 | 110 |
关联 | 111 |
关联命名 | 113 |
关联的每一端称为角色 | 113 |
两个类之间的多重关联 | 114 |
属性 | 117 |
恰当的属性 | 117 |
何时定义新的数据类型 | 120 |
任何属性都不表示外键 | 121 |
什么是系统顺序图 | 128 |
UML顺序图和系统顺序图(SSD) | 129 |
如何为系统事件和操作命名 | 130 |
SSD与词汇表 | 130 |
为什么需要操作契约 | 133 |
什么是系统操作 | 135 |
操作契约的组成部分 | 135 |
编写操作契约的步骤 | 139 |
为什么需要分层体系结构 | 147 |
使用层进行设计 | 149 |
使用层解决的问题 | 149 |
不要将外部资源表示为最底层 | 153 |
模型-视图分离原则 | 154 |
什么是动态模型和静态模型 | 156 |
交互图比类图重要 | 159 |
CRC卡 | 159 |
交互图的两种类型 | 161 |
顺序图和通信图的优点和缺点 | 163 |
交互图中的单实例对象 | 165 |
顺序图的基本表示法 | 166 |
表示回答或返回 | 167 |
发送给自身的消息 | 167 |
UML顺序图中的图框 | 168 |
交互图的关联 | 172 |
主动对象 | 174 |
UML顺序图中异步和同步调用的表示 | 174 |
通信图的基本表示法 | 175 |
UML类图中的类型 | 180 |
属性表示 | 182 |
表示集合属性 | 185 |
依赖 | 189 |
组合优于聚合 | 191 |
UML类图中接口的表示 | 191 |
限定关联 | 192 |
UML类图中单实例类的表示 | 193 |
职责和职责驱动设计 | 198 |
行为职责和认知职责 | 200 |
GRASP的作用 | 200 |
什么是模式 | 201 |
怎样降低依赖性,减少变化带来的影响 | 206 |
耦合与低耦合 | 206 |
高内聚 | 227 |
内聚性低导致的问题 | 227 |
内聚程度的一些场景 | 229 |
内聚与耦合的关系 | 229 |
创建者 | 210 |
最好把创建职责委派给工厂类 | 212 |
信息专家 | 212 |
信息专家的优点 | 215 |
控制器 | 208 |
控制器的优点 | 209 |
对象的可见性 | 261-262 |
实现全局可见性的推荐方法是使用单实例类 | 264 |
变量作用域的管理 | 265 |
将设计映射为代码 | 265 |
多态所解决的问题 | 301 |
何时使用接口、何时不使用接口 | 300 |
纯虚构 | 306 |
间接性 | 309 |
防止变异 | 310 |
防止变异的方法 | 311 |
与保护变化有关的几个原则 | 312 |
变化点和进化点 | 314 |
单实例类(单例模式) | 321 |
不能将单实例类中的所有方法定义为静态方法的原因 | 323 |
适配器模式 | 317 \ 324 |
工厂模式 | 319 |
策略模式 | 324 |
使用工厂和单例模式创建策略对象 | 327 |
观察者模式 | 337 |
观察者模式的特点 | 340 |
MVC | 316 |
活动图的应用 | 346 |
使用活动图建模的一些准则 | 350 |
令牌 | 351 |
UML状态机图 | 352 |
用例关联简介(作用) | 357 |
用例的包含关系 | 358 |
包含关系的使用场景 | 359 |
扩展关系 | 360 |
识别领域模型中概念的方法 | 364 |
泛化 | 365 |
泛化准则 | 367 |
将概念划分为子类的动机 | 368 |
何时定义概念超类 | 369 |
抽象概念类 | 371 |
对变化的状态建模 | 372 |
关联类 | 373-374 |
领域模型中引入关联类的场景 | 375 |
组合和聚合关系 | 375-376 |
使用组合关系的情形 | 376 |
显示组合关系的用处 | 376 |
使用包来组织领域模型 | 380 |
如何划分领域模型 | 381 |
组织包结构的准则 | 381 |