跳转至

面向对象技术:题库练习

已整理本章知识点练习 181 条来源题目,共 179 道练习。题号沿用来源序号;同材料的不同小问分别保留。

题干保留事实条件、选项与必要题图;平台答案、整理解析与纠错默认收起。解析重新归纳为复习笔记,平台答案不等同于官方答案。

题库整理进度 · 历年试卷清单

知识点练习

题目 001

来源:知识点练习「面向对象技术」第 1 题(原站入口)。

在类模型中,一个一般类与一个或多个由它细化出的特殊类之间,属于哪一种关系( )?

  • A. 泛化

  • B. 关联

  • C. 聚集

  • D. 组合

答案与解析

平台答案:A。

整理解析

选 A。泛化表示一般类型与特殊类型的关系,特殊类型继承一般类型的特征。关联描述连接,聚集和组合描述整体与部分;这些关系都不等同于类型细化。

题目 002

来源:知识点练习「面向对象技术」第 2 题(原站入口)。

程序运行期间,对象收到服务请求后,依据接收对象的实际情况,才把请求的操作连接到具体实现方法。这种机制称为什么( )?

  • A. 静态绑定

  • B. 通用绑定

  • C. 动态绑定

  • D. 过载绑定

答案与解析

平台答案:C。

整理解析

选 C。方法实现到运行时才按接收对象的实际类型确定,属于动态绑定;编译时就确定目标的调用属于静态绑定。

题目 003

来源:知识点练习「面向对象技术」第 3 题(原站入口)。

不同对象对同一消息可给出不同响应,这种现象称为(3),题述通过(4)机制支持:把通用功能的消息置于类层次的上层,把各自实现放在下层,由下层类的对象作出不同响应。

请作答:第 3 题。

  • A. 绑定

  • B. 继承

  • C. 消息

  • D. 多态

答案与解析

平台答案:D。

整理解析

选 D。同一操作在不同类型对象上表现不同,是多态。题述特指基于类型层次的多态;平台用父类指针和虚函数说明的是 C++ 的一种实现,不能据此把所有语言、所有多态都限定为这种写法。

题目 004

来源:知识点练习「面向对象技术」第 4 题(原站入口)。

不同对象对同一消息可给出不同响应,这种现象称为(3),题述通过(4)机制支持:把通用功能的消息置于类层次的上层,把各自实现放在下层,由下层类的对象作出不同响应。

请作答:第 4 题。

  • A. 绑定

  • B. 继承

  • C. 消息

  • D. 多态

答案与解析

平台答案:B。

整理解析

选 B。题干明确使用上层类与下层类组织共同操作及不同实现,所问结构机制是继承。运行时选择哪个重写实现还涉及动态绑定;继承本身不等于动态绑定,也不是参数多态等所有多态形式的必要条件。

题目 005

来源:知识点练习「面向对象技术」第 5 题(原站入口)。

要继续细化一个复杂用例内部的业务处理流程,以下哪种 UML 图最适合( )?

  • A. 状态图

  • B. 顺序图

  • C. 类图

  • D. 活动图

答案与解析

平台答案:D。

整理解析

选 D。活动图能直接表达步骤、分支、合并及并发等流程。状态图关注对象状态及转换,顺序图关注消息先后,类图描述静态结构。

题目 006

来源:知识点练习「面向对象技术」第 6 题(原站入口)。

阅读下列序列图:其中(6)是返回消息;Account 类需要提供的方法为(7)。

题目配图

请作答:第 6 题。

  • A. tansID

  • B. balance

  • C. withdraw

  • D. deposit

答案与解析

平台答案:B。

整理解析

选 B。图中第3条 balance 消息用虚线从 src:Account 指回事务管理对象,表示 checkBalance 调用的返回;withdraw 与 deposit 都是发向 Account 对象的调用。选项A保留来源的 tansID 写法,图中的 transID 是传入参数,不影响本题判断。

题目 007

来源:知识点练习「面向对象技术」第 7 题(原站入口)。

阅读下列序列图:其中(6)是返回消息;Account 类需要提供的方法为(7)。

题目配图

请作答:第 7 题。

  • A. start()

  • B. checkBalance()和withdraw()

  • C. deposit()

  • D. checkBalance()、withdraw()和deposit()

答案与解析

平台答案:D。

整理解析

选 D。发给 src:Account 的调用是 checkBalance 和 withdraw,发给 tgt:Account 的调用是 deposit;两个接收对象同属 Account 类,因此三种操作都应由该类支持。start 的接收者是事务管理对象,不是 Account。

题目 008

来源:知识点练习「面向对象技术」第 8 题(原站入口)。

根据下面的类及调用关系图,识别设计模式(8),并选择与其匹配的使用场景(9)。

题目配图

请作答:第 8 题。

  • A. 适配器(Adapter)

  • B. 责任链(Chain of Responsibility)

  • C. 外观(Facade)

  • D. 桥接(Bridge)

答案与解析

平台答案:C。

整理解析

选 C。图中 Compiler 提供 Compile 入口,并协调扫描器、语法分析器、代码生成器等子系统对象,符合外观模式用统一入口封装复杂调用的意图。不能只凭某个类名判断,应结合这些对外入口与内部依赖。

题目 009

来源:知识点练习「面向对象技术」第 9 题(原站入口)。

根据下面的类及调用关系图,识别设计模式(8),并选择与其匹配的使用场景(9)。

题目配图

请作答:第 9 题。

  • A. 有多个对象可以处理一个请求,在运行时刻自动确定由哪个对象处理

  • B. 想使用一个已经存在的类,而其接口不符合要求

  • C. 类的抽象和其实现之间不希望有一个固定的绑定关系

  • D. 需要为一个复杂子系统提供一个简单接口

答案与解析

平台答案:D。

整理解析

选 D。Compiler 的统一入口简化客户端使用编译子系统的方式,适合复杂子系统需要简单接口的场景。A对应责任链,B对应适配器,C对应桥接。

题目 010

来源:知识点练习「面向对象技术」第 10 题(原站入口)。

在所列模式中,(10)既有类结构型形式,也有对象结构型形式。它与(11)都能通过间接层,从对象自身以外的接口向该对象转发请求。

请作答:第 10 题。

  • A. 桥接(Bridge)

  • B. 适配器(Adapter)

  • C. 组成(Composite)

  • D. 装饰器(Decorator)

答案与解析

平台答案:B。

整理解析

选 B。适配器可借助继承实现类适配,也可持有适配对象并委托实现对象适配,因此同时有两种结构型形式。它的目的在于连接不兼容接口。

题目 011

来源:知识点练习「面向对象技术」第 11 题(原站入口)。

在所列模式中,(10)既有类结构型形式,也有对象结构型形式。它与(11)都能通过间接层,从对象自身以外的接口向该对象转发请求。

请作答:第 11 题。

  • A. 桥接(Bridge)

  • B. 适配器(Adapter)

  • C. 组成(Composite)

  • D. 装饰器 (Decorator)

答案与解析

平台答案:A。

整理解析

平台选 A。桥接让抽象对象把工作交给所持有的实现对象,与适配器一样包含间接调用。两者意图不同:桥接支持抽象与实现分别变化,适配器解决接口不兼容。仅有转发行为不足以唯一识别一个模式,仍须结合设计意图。

题目 012

来源:知识点练习「面向对象技术」第 12 题(原站入口)。

下面哪一对类存在一般类型与特殊类型的关系( )?

  • A. 汽车与轮船

  • B. 交通工具与飞机

  • C. 轮船与飞机

  • D. 汽车与飞机

答案与解析

平台答案:B。

整理解析

选 B。飞机是一类交通工具,可建立从飞机到交通工具的泛化关系;其他各对都是并列的具体交通工具类别。

题目 013

来源:知识点练习「面向对象技术」第 13 题(原站入口)。

将多态区分为参数、包含、过载和强制四类时,以子类型化为典型例子、在许多语言中都存在的是哪一种( )?

  • A. 参数

  • B. 包含

  • C. 过载

  • D. 强制

答案与解析

平台答案:B。

整理解析

选 B。子类型对象可在需要其父类型的位置使用,这属于包含多态。参数多态对应类型参数,过载多态对应同名的不同签名,强制多态对应类型转换。纠错:包含多态不必依赖运行时类型检查;Java 可在编译期检查子类型兼容性,再在运行时分派重写方法,动态分派与类型检查是不同事情。

题目 014

来源:知识点练习「面向对象技术」第 14 题(原站入口)。

在面向对象语言中,对象之间通过(14)通信。关于良好的面向对象语言应支持哪些能力,下列不正确的说法是(15)。

请作答:第 14 题。

  • A. 消息传递

  • B. 继承

  • C. 引用

  • D. 多态

答案与解析

平台答案:A。

整理解析

选 A。面向对象模型把请求接收对象执行操作称为消息传递,常落实为方法调用。纠错:消息传递是交互模型,指针或引用是实现中定位对象的手段,两者不互斥;例如 C++ 可通过对象指针调用方法。

题目 015

来源:知识点练习「面向对象技术」第 15 题(原站入口)。

在面向对象语言中,对象之间通过(14)通信。关于良好的面向对象语言应支持哪些能力,下列不正确的说法是(15)。

请作答:第 15 题。

  • A. 应该支持被封装的对象

  • B. 应该支持类写实例的概念

  • C. 应该支持通过指针进行引用

  • D. 应该支持继承和多态

答案与解析

平台答案:C。

整理解析

按将选项理解为所有面向对象语言都应具备的要求,平台选 C:显式指针不是面向对象的必要条件。不能解释成面向对象语言禁止指针,C++ 本身就允许使用指针。原页已核实:B确为“应该支持类写实例的概念”;保留“写”字,疑为“与”的笔误。按类及实例这一通常意图理解,它指面向对象的基本抽象。

题目 016

来源:知识点练习「面向对象技术」第 16 题(原站入口)。

按 UML 的结构、行为、分组、注释四类事物划分,类、接口、构件属于(16)事物;附加在一个或多个元素上、表达约束或说明的简单符号属于(17)事物。

请作答:第 16 题。

  • A. 结构

  • B. 行为

  • C. 分组

  • D. 注释

答案与解析

平台答案:A。

整理解析

选 A。类、接口、构件描述模型中的静态组成,归于结构事物;行为事物侧重交互、状态机等动态行为。

题目 017

来源:知识点练习「面向对象技术」第 17 题(原站入口)。

按 UML 的结构、行为、分组、注释四类事物划分,类、接口、构件属于(16)事物;附加在一个或多个元素上、表达约束或说明的简单符号属于(17)事物。

请作答:第 17 题。

  • A. 结构

  • B. 行为

  • C. 分组

  • D. 注释

答案与解析

平台答案:D。

整理解析

选 D。给模型元素附加文字说明或约束的注释符号属于注释事物,不是组织元素的包,也不是行为或结构本体。

题目 018

来源:知识点练习「面向对象技术」第 18 题(原站入口)。

一组对象的通信虽有明确规则,但交互复杂、相互依赖难以理解。用(18)模式以一个中介对象集中封装交互,让各对象无需直接相互引用,并可独立调整交互规则。题目把它与(19)作为对照:前者集中封装通信,后者引入其他对象分布通信,称两者为相互竞争的模式。

请作答:第 18 题。

  • A. 解释器(Interpreter)

  • B. 策略(Strategy)

  • C. 中介者(Mediator)

  • D. 观察者(Observer)

答案与解析

平台答案:C。

整理解析

选 C。把复杂的多方协作规则交给专门对象统一协调,正是中介者模式;参与对象主要与中介者通信。限定:这不表示中介者与观察者不能共用,中介者也可通过订阅通知与各对象交互。

题目 019

来源:知识点练习「面向对象技术」第 19 题(原站入口)。

一组对象的通信虽有明确规则,但交互复杂、相互依赖难以理解。用(18)模式以一个中介对象集中封装交互,让各对象无需直接相互引用,并可独立调整交互规则。题目把它与(19)作为对照:前者集中封装通信,后者引入其他对象分布通信,称两者为相互竞争的模式。

请作答:第 19 题。

  • A. 解释器(Interpreter)

  • B. 策略(Strategy)

  • C. 中介者(Mediator)

  • D. 观察者(Observer)

答案与解析

平台答案:D。

整理解析

选 D。观察者通过主题与订阅者之间的通知关系分布通信;中介者则把跨对象协作规则集中管理。这是两者设计侧重点的比较,并不禁止在同一系统中同时采用。

题目 020

来源:知识点练习「面向对象技术」第 20 题(原站入口)。

UML 交互图描述对象之间的交互,包含参与交互的对象、关系以及可能传递的消息。以下哪种图不属于交互图( )?

  • A. 序列图

  • B. 对象图

  • C. 通信图

  • D. 时序图

答案与解析

平台答案:B。

整理解析

选 B。对象图给出某一时刻实例及其连接的静态快照,不描绘消息交互。序列图和通信图属于交互图;“时序图”不论在此用作序列图的别名还是指 Timing Diagram,也都属于交互图。补充:UML 2还包括交互概览图,不能把交互图种类局限为旧版常见的两种。

题目 021

来源:知识点练习「面向对象技术」第 21 题(原站入口)。

根据下图识别设计模式(21),并选择该模式适用的情形(22)。

题目配图

请作答:第 21 题。

  • A. 抽象工厂(Abstract Factory)

  • B. 生成器(Builder)

  • C. 工厂方法(Factory Method)

  • D. 原型(Prototype)

答案与解析

平台答案:B。

整理解析

选 B。Director 控制构建步骤,通过 Builder 调用 BuildPart;ConcreteBuilder 负责具体构建并提供 GetResult 获取 Product。这一职责分工对应生成器模式。

题目 022

来源:知识点练习「面向对象技术」第 22 题(原站入口)。

根据下图识别设计模式(21),并选择该模式适用的情形(22)。

题目配图

请作答:第 22 题。

  • A. 一个系统要由多个产品系列中的一个来配置时

  • B. 当一个类希望由它的子类来指定它所创建的对象时

  • C. 当创建复杂对象的算法应该独立于该对象的组成部分及其装配方式时

  • D. 当一个系统应该独立于它的产品创建、构成和表示时

答案与解析

平台答案:C。

整理解析

选 C。生成器把构建过程与具体部件及表示分开,使相同的构建流程可以产生不同产品表示。A侧重产品族,B侧重把实例化决定交给子类;D是多种创建型模式共有的宽泛目标,C与图中逐步构建的意图最直接。

题目 023

来源:知识点练习「面向对象技术」第 23 题(原站入口)。

对象、类、继承和消息传递被列为面向对象的4个核心概念。其中,一个对象将什么封装成整体( )?

  • A. 命名空间

  • B. 要完成任务

  • C. 一组数据

  • D. 数据和行为

答案与解析

平台答案:D。

整理解析

选 D。对象既保存属性所表示的状态,又提供操作这些状态的行为;仅有数据集合不足以概括对象。

题目 024

来源:知识点练习「面向对象技术」第 24 题(原站入口)。

在面向对象开发中,哪一环节负责选用合适的面向对象语言,把程序写成协作的对象集合,并通过继承等关系组织对象所属的类( )?

  • A. 分析

  • B. 设计

  • C. 程序设计

  • D. 测试

答案与解析

平台答案:C。

整理解析

选 C。选定语言并实现相互协作的对象属于面向对象程序设计。分析侧重问题域及需求,设计侧重实现方案与职责划分;平台把实现源代码并入设计的说法应与编码阶段区分。

题目 025

来源:知识点练习「面向对象技术」第 25、111 题(原站入口)。

同一个类中,若有多个方法名称相同、参数类型列表不同,这种机制叫什么( )?

  • A. 重载

  • B. 调用

  • C. 重置

  • D. 标记

答案与解析

平台答案(来源第 25 题):A。

整理解析(来源第 25 题)

选 A。相同方法名配合不同参数列表构成重载。以 Java 为例,重载选择主要依据编译期可见的签名及实参类型;仅返回类型不同不能建立重载,重载也不同于子类重写同签名方法。

来源第 111 题对照

原题题干

同一类中有多个同名方法,它们的参数类型、参数个数或参数类型排列顺序不同。这称为什么?

原题选项对照

原选项内容本页选项
A

方法标记

D
B

方法调用

B
C

方法重载

A
D

方法覆盖

C

原平台答案(来源第 111 题,原题选项):C;对应本页选项:A;本页平台答案:A。

整理解析(来源第 111 题)

选C,这是方法重载;方法覆盖通常指子类重新实现继承来的可覆盖方法。平台称方法由名称、参数表和返回类型唯一标识,不能普遍套用:在Java、C++等常见语言中,仅返回类型不同不足以构成重载。

题目 026

来源:知识点练习「面向对象技术」第 26 题(原站入口)。

在 UML 的依赖、关联、泛化、实现四种关系中,(26)是描述一组对象连接即“链”的结构关系;(27)描述特殊元素与一般元素之间的关系,使子元素共享父元素的结构和行为。

请作答:第 26 题。

  • A. 依赖

  • B. 关联

  • C. 泛化

  • D. 实现

答案与解析

平台答案:B。

整理解析

选 B。关联描述类型之间可存在怎样的连接,链则是具体对象间的一次连接,即关联的实例。它与一般—特殊的类型层次关系不同。

题目 027

来源:知识点练习「面向对象技术」第 27 题(原站入口)。

在 UML 的依赖、关联、泛化、实现四种关系中,(26)是描述一组对象连接即“链”的结构关系;(27)描述特殊元素与一般元素之间的关系,使子元素共享父元素的结构和行为。

请作答:第 27 题。

  • A. 依赖

  • B. 关联

  • C. 泛化

  • D. 实现

答案与解析

平台答案:C。

整理解析

选 C。泛化把特殊分类器连接到一般分类器,特殊者继承一般者的特征,常画为指向一般者的实线空心三角箭头。实现关系则表示履行接口等所规定的契约。

题目 028

来源:知识点练习「面向对象技术」第 28 题(原站入口)。

使用 UML 为新系统的需求建模、规划功能或据此安排测试用例,最合适的是(28);若要展示交付系统的软件组件与硬件之间的配置关系,则应使用(29)。

请作答:第 28 题。

  • A. 类图

  • B. 对象图

  • C. 用例图

  • D. 交互图

答案与解析

平台答案:C。

整理解析

选 C。用例图从参与者使用系统的目标出发描述外部可见功能,适合组织功能需求并为测试场景提供依据。它不负责给出软件在硬件节点上的放置位置。

题目 029

来源:知识点练习「面向对象技术」第 29 题(原站入口)。

使用 UML 为新系统的需求建模、规划功能或据此安排测试用例,最合适的是(28);若要展示交付系统的软件组件与硬件之间的配置关系,则应使用(29)。

请作答:第 29 题。

  • A. 类图

  • B. 部署图

  • C. 组件图

  • D. 网络图

答案与解析

平台答案:B。

整理解析

选 B。部署图展示运行节点、执行环境和部署其上的制品,可表达软件与硬件的配置对应;组件图主要表达软件组件本身的结构。严格按 UML 2,部署到节点的是制品,组件通常由制品体现。

题目 030

来源:知识点练习「面向对象技术」第 30 题(原站入口)。

观察下图,判断模式名称(30)、所属类别(31),以及适用场景(32)。

题目配图

请作答:第 30 题。

  • A. 代理(Proxy)

  • B. 生成器(Builder)

  • C. 组合(Composite)

  • D. 观察者(Observer)

答案与解析

平台答案:C。

整理解析

选 C。Leaf 和 Composite 都是 Component 的子类型,而 Composite 又保存多个 Component,因此叶子对象与容器对象可以按同一接口处理,形成组合模式。图中空心菱形表示聚合关系;“组合设计模式”这一名称不要求使用 UML 实心菱形的组合关系。

题目 031

来源:知识点练习「面向对象技术」第 31 题(原站入口)。

观察下图,判断模式名称(30)、所属类别(31),以及适用场景(32)。

题目配图

请作答:第 31 题。

  • A. 创建型

  • B. 结构型

  • C. 行为

  • D. 结构型和行为

答案与解析

平台答案:B。

整理解析

选 B。该模式通过统一抽象把叶子与容器组织成层次结构,重点是对象如何组成更大的结构,所以属于结构型模式。

题目 032

来源:知识点练习「面向对象技术」第 32 题(原站入口)。

观察下图,判断模式名称(30)、所属类别(31),以及适用场景(32)。

题目配图

请作答:第 32 题。

  • A. 表示对象的部分一整体层次结构时

  • B. 当一个对象必须通知其他对象,而它又不能假定其他对象是谁时

  • C. 当创建复杂对象的算法应该独立于该对象的组成部分及其装配方式时

  • D. 在需要比较通用和复杂的对象指针代替简单的指针时

答案与解析

平台答案:A。

整理解析

选 A。Composite 可聚合多个 Component,而 Component 又可以是 Leaf 或 Composite,正好表达整体—部分的递归层次。图中 Component 端的 * 表示一个 Composite 可关联零个或多个 Component,不能把该多重度反向读成一个部件一定归属多个整体。

题目 033

来源:知识点练习「面向对象技术」第 33 题(原站入口)。

有的设计模式引入主要用作参数的对象。哪一种对象会作为多态 accept 方法的参数( )?

  • A. Visitor

  • B. Command

  • C. Memento

  • D. Observer

答案与解析

平台答案:A。

整理解析

选 A。在访问者模式中,被访问元素提供 accept(visitor),并在其实现中回调适合该具体元素的 visit 操作。传入的是 Visitor 对象,由此把要对元素执行的操作与元素结构分离。

题目 034

来源:知识点练习「面向对象技术」第 34 题(原站入口)。

在面向对象系统中,对象是运行时实体。它的组成不包括(34);一个类所定义的一组相似对象则共享(35)。

请作答:第 34 题。

  • A. 消息

  • B. 行为(操作)

  • C. 对象名

  • D. 状态

答案与解析

平台答案:A。

整理解析

选 A。教材通常把对象概括为标识、状态和行为;消息是请求对象执行操作的交互信息。选项“对象名”在此用于表示标识,但真实系统中的对象不一定具有程序员显式命名的变量名。

题目 035

来源:知识点练习「面向对象技术」第 35 题(原站入口)。

在面向对象系统中,对象是运行时实体。它的组成不包括(34);一个类所定义的一组相似对象则共享(35)。

请作答:第 35 题。

  • A. 属性和状态

  • B. 对象名和状态

  • C. 行为和多重度

  • D. 属性和行为

答案与解析

平台答案:D。

整理解析

选 D。同类对象共享属性的定义及可提供的行为,但各个实例的属性值可以不同,所以不能把“共享属性”理解成所有对象共享同一份状态。

题目 036

来源:知识点练习「面向对象技术」第 36 题(原站入口)。

在下面的 UML 类图中,Car 和 Boat 中的 move() 与 Transport 中的同名方法是什么关系( )?

题目配图

  • A. 继承

  • B. 覆盖(重置)

  • C. 重载

  • D. 聚合

答案与解析

平台答案:B。

整理解析

选 B。图中空心三角指向 Transport,表明 Car、Boat 是其特殊类型;子类各自提供同签名的 move(),题意是覆盖即重写。参数列表不同才对应重载,不能仅凭方法名相同就判定为重载。

题目 037

来源:知识点练习「面向对象技术」第 37 题(原站入口)。

根据下列 UML 图,分别识别标注(I)、(Ⅱ)、(Ⅲ)所指元素,依次填入(37)、(38)、(39)。

题目配图

请作答:第 37 题。

  • A. 参与者

  • B. 用例

  • C. 泛化关系

  • D. 包含关系

答案与解析

平台答案:A。

整理解析

选 A。(I)指向标为 Trader 的小人符号,是系统外部的参与者。参与者表示与系统交互的角色,不要求一定是自然人。

题目 038

来源:知识点练习「面向对象技术」第 38 题(原站入口)。

根据下列 UML 图,分别识别标注(I)、(Ⅱ)、(Ⅲ)所指元素,依次填入(37)、(38)、(39)。

题目配图

请作答:第 38 题。

  • A. 参与者

  • B. 用例

  • C. 泛化关系

  • D. 包含关系

答案与解析

平台答案:C。

整理解析

选 C。(Ⅱ)指向 Limits Exceeded 与 Capture Deal 之间的实线空心三角箭头,是泛化关系,三角端 Capture Deal 为一般用例。即使从业务名称联想到扩展,也必须依据原图符号判断;include 是另两处带标签的虚线箭头。

题目 039

来源:知识点练习「面向对象技术」第 39 题(原站入口)。

根据下列 UML 图,分别识别标注(I)、(Ⅱ)、(Ⅲ)所指元素,依次填入(37)、(38)、(39)。

题目配图

请作答:第 39 题。

  • A. 参与者

  • B. 用例

  • C. 泛化关系

  • D. 包含关系

答案与解析

平台答案:B。

整理解析

选 B。(Ⅲ)指向写着 Limits Exceeded 的椭圆,该符号表示用例;用例之间的连线才表示关系。

题目 040

来源:知识点练习「面向对象技术」第 40 题(原站入口)。

判断下面这张图属于哪一种 UML 图( )?

题目配图

  • A. 类图

  • B. 部署图

  • C. 组件图

  • D. 网络图

答案与解析

平台答案:C。

整理解析

选 C。图中用构件符号表示 Bookingsdll、Servicesdll、GUIlib 和 Main.exe,并用虚线箭头连接其依赖,描述的是组件结构。图上没有部署节点,不能仅因出现文件名便认定为部署图。

题目 041

来源:知识点练习「面向对象技术」第 41 题(原站入口)。

关于 Singleton(单例)模式,下面哪项描述不正确( )?

  • A. 单例模式是创建型模式

  • B. 单例模式保证一个类仅有一个实例

  • C. 单例类提供一个访问唯一实例的全局访问点

  • D. 单例类提供一个创建一系列相关或相互依赖对象的接口

答案与解析

平台答案:D。

整理解析

选 D。创建一组相关或相互依赖产品的接口属于抽象工厂的意图;单例关注控制某个类的实例数量并提供统一访问点,是创建型模式。

题目 042

来源:知识点练习「面向对象技术」第 42 题(原站入口)。

给对象动态增加额外职责而不改动它自身结构,可用(42)模式;由统一创建接口把具体实例化决定交给子类,可用(43)模式;若一个后端数据模型要连接多个前端用户界面,题目要求选择最适合的(44)模式。

请作答:第 42 题。

  • A. 组合(Composite)

  • B. 外观(Facade)

  • C. 享元(Flyweight)

  • D. 装饰器(Decorator)

答案与解析

平台答案:D。

整理解析

选 D。装饰器持有原对象,在保持相容接口的同时,在委托调用前后附加职责。这样可按对象动态组合功能,无需改动被包装对象的类定义。

题目 043

来源:知识点练习「面向对象技术」第 43 题(原站入口)。

给对象动态增加额外职责而不改动它自身结构,可用(42)模式;由统一创建接口把具体实例化决定交给子类,可用(43)模式;若一个后端数据模型要连接多个前端用户界面,题目要求选择最适合的(44)模式。

请作答:第 43 题。

  • A. 工厂方法(Factory Method)

  • B. 享元(Flyweight)

  • C. 观察者( Observer)

  • D. 中介者(Mediator)

答案与解析

平台答案:A。

整理解析

选 A。工厂方法把创建操作定义在抽象层,由具体子类决定返回何种产品,把具体类的选择推迟到扩展实现。

题目 044

来源:知识点练习「面向对象技术」第 44 题(原站入口)。

给对象动态增加额外职责而不改动它自身结构,可用(42)模式;由统一创建接口把具体实例化决定交给子类,可用(43)模式;若一个后端数据模型要连接多个前端用户界面,题目要求选择最适合的(44)模式。

请作答:第 44 题。

  • A. 装饰器(Decorator)

  • B. 享元(Flyweight)

  • C. 观察者(Observer)

  • D. 中介者(Mediator)

答案与解析

平台答案:D。

整理解析

平台答案保留 D(中介者)。原页已核实:第三空只说一个后端数据模型连接多个前端界面,没有复杂协调或更新通知的限定,前两空也未补足条件。若意图是模型变化时各界面同步更新,通常采用 C 观察者;中介者则适合集中协调多方交互。仅有“连接多个界面”不能唯一推出D,故保留原站答案并明确条件不足,不将D解释为无争议的唯一结论。

题目 045

来源:知识点练习「面向对象技术」第 45 题(原站入口)。

在面向对象方法中,父类与子类共享数据及方法的机制称为(45);子类沿用父类接口、用自身需要的实现替换相应父类实现,称为(46)。

请作答:第 45 题。

  • A. 封装

  • B. 继承

  • C. 覆盖

  • D. 多态

答案与解析

平台答案:B。

整理解析

选 B。继承使子类获得父类的特征并可扩展行为。这里的“共享”是特征定义或实现的复用,不表示所有父子类实例共用同一份实例数据。

题目 046

来源:知识点练习「面向对象技术」第 46 题(原站入口)。

在面向对象方法中,父类与子类共享数据及方法的机制称为(45);子类沿用父类接口、用自身需要的实现替换相应父类实现,称为(46)。

请作答:第 46 题。

  • A. 封装

  • B. 继承

  • C. 覆盖

  • D. 多态

答案与解析

平台答案:C。

整理解析

选 C。子类在既有操作契约下给出新的实现是覆盖,即重写。重载则是相同名称配合不同参数列表,不能混同。

题目 047

来源:知识点练习「面向对象技术」第 47 题(原站入口)。

UML 用例图中的参与者,表示以下哪一种概念( )?

  • A. 人、硬件或其他系统可以扮演的角色

  • B. 可以完成多种动作的相同用户

  • C. 不管角色的实际物理用户

  • D. 带接口的物理系统或者硬件设计

答案与解析

平台答案:A。

整理解析

选 A。参与者是相对于所建模系统的外部交互角色,可由人、硬件或其他系统承担。同一个人可以扮演多个角色,多个实际实体也可以扮演同一角色。

题目 048

来源:知识点练习「面向对象技术」第 48 题(原站入口)。

UML 中关联描述一组对象间的链。对于两个类之间可以建立的关联,以下说法哪项合适( )?

  • A. 不能有多个

  • B. 可以有多个由不同角色标识的

  • C. 可以有任意多个

  • D. 多个关联必须聚合成一个

答案与解析

平台答案:B。

整理解析

选 B。同一对类可基于不同业务角色建立不同关联,例如同一用户类与试卷类可分别表达学员和普通网友的测试关系。多个关联应有可区分的语义,不能被强制压成一个;角色名是常用区分方式,而不是所有UML关联都必须写角色名的语法规则。

题目 049

来源:知识点练习「面向对象技术」第 49 题(原站入口)。

识别下列 UML 图的类型(49),并分别说明标注(Ⅰ)与(Ⅱ)表示什么(50)、(51)。

题目配图

请作答:第 49 题。

  • A. 序列图

  • B. 状态图

  • C. 通信图

  • D. 活动图

答案与解析

平台答案:D。

整理解析

选 D。图按接单、履约、开票、收款等动作组织控制流,并使用分叉和汇合表达并发,是活动图。纠错:不能按“状态图每条箭头都有事件”来机械判断;状态机允许没有显式触发事件的完成转换。

题目 050

来源:知识点练习「面向对象技术」第 50 题(原站入口)。

识别下列 UML 图的类型(49),并分别说明标注(Ⅰ)与(Ⅱ)表示什么(50)、(51)。

题目配图

请作答:第 50 题。

  • A. 合并分叉

  • B. 分支

  • C. 合并汇合

  • D. 流

答案与解析

平台答案:A。

整理解析

平台答案为 A。原图(Ⅰ)的粗横条有一条流进入、两条流离开,将处理拆成并发路径,是分叉节点(fork);下方多入一出的粗横条才是汇合(join)。原页已核实:A确写“合并分叉”。保留原选项,其意图应为并发分叉,不能把该非标准用词当作UML正式名称。

题目 051

来源:知识点练习「面向对象技术」第 51 题(原站入口)。

识别下列 UML 图的类型(49),并分别说明标注(Ⅰ)与(Ⅱ)表示什么(50)、(51)。

题目配图

请作答:第 51 题。

  • A. 分支条件

  • B. 监护表达式

  • C. 动作名

  • D. 流名称

答案与解析

平台答案:B。

整理解析

选 B。(Ⅱ)指向方括号中的 [not complete],这是监护表达式,即守卫条件;只有条件为真,相应控制流才可通过。动作名是 Fill Order 等节点文字,不是这段条件。

题目 052

来源:知识点练习「面向对象技术」第 52 题(原站入口)。

为 GUI 组件提供不同平台上对应的成套类层次结构,应采用哪一种模式( )?

  • A. 享元(Flyweight)

  • B. 抽象工厂(Abstract Factory)

  • C. 外观(Facade))

  • D. 装饰器(Decorator)

答案与解析

平台答案:B。

整理解析

选 B。各平台通常需要彼此配套的按钮、窗口等组件,抽象工厂为这一组产品规定统一创建接口,由具体平台工厂产生相容的一整套组件。

题目 053

来源:知识点练习「面向对象技术」第 53 题(原站入口)。

把请求封装为对象,以便使用不同请求对客户进行参数化,并可对请求排队、记录日志及支持撤销,这描述哪种模式( )?

  • A. 命令(Command)

  • B. 责任链(Chain of Responsibility)

  • C. 观察者(Observer)

  • D. 策略(Strategy)

答案与解析

平台答案:A。

整理解析

选 A。命令对象把接收者和待执行操作封装起来,调用者可统一保存、调度或记录这些请求。撤销仍需命令实现相应逆操作或保存恢复状态,并非只封装请求就自动得到。

题目 054

来源:知识点练习「面向对象技术」第 54 题(原站入口)。

订阅者注册某个主题后,主题出现新消息便通知订阅者。以下哪种模式最适合表达这一发布/订阅关系( )?

  • A. 适配器(Adapter)

  • B. 通知(Notifier)

  • C. 观察者(Observer)

  • D. 状态(State)

答案与解析

平台答案:C。

整理解析

选 C。观察者将主题变化与订阅者通知联系起来,形成一对多依赖。工程中的消息代理式发布订阅还能进一步解耦双方,不必与对象直接注册回调的具体实现完全相同。

题目 055

来源:知识点练习「面向对象技术」第 55 题(原站入口)。

大量对象带来较大存储开销,希望通过共享减少对象数量、降低内存占用并改善性能,应选哪种模式( )?

  • A. 组合(Composite)

  • B. 享元(Flyweight)

  • C. 迭代器(Iterator)

  • D. 备忘录(Memento)

答案与解析

平台答案:B。

整理解析

选 B。享元共享可复用的内部状态,把随使用场景变化的外部状态留给调用方。能共享的状态足够多时才有明显收益,不能把任意可变对象直接合并。

题目 056

来源:知识点练习「面向对象技术」第 56 题(原站入口)。

不同对象收到同一通用消息可以产生不同结果,调用者只发送该消息,具体实现由接收对象决定。这种现象叫什么( )?

  • A. 接口

  • B. 继承

  • C. 覆盖

  • D. 多态

答案与解析

平台答案:D。

整理解析

选 D。这是对象对同一操作表现不同的多态性;调用者依赖共同接口,实际接收对象执行自身的实现。继承和覆盖可以参与实现这种行为,但并非该现象本身的名称。

题目 057

来源:知识点练习「面向对象技术」第 57 题(原站入口)。

在所列机制中,哪一种支持面向对象的多态行为( )?

  • A. 静态分配

  • B. 动态分配

  • C. 静态类型

  • D. 动态绑定

答案与解析

平台答案:D。

整理解析

选 D。本题按运行时对象多态理解:动态绑定依据实际接收对象选择重写实现。限定:软考的广义多态还包括参数、过载和强制多态,不能推成所有多态都必须动态绑定;Java 的重载选择通常在编译期完成。

题目 058

来源:知识点练习「面向对象技术」第 58 题(原站入口)。

面向对象分析旨在理解应用问题。以下哪项不属于这一阶段的主要活动( )?

  • A. 认定并组织对象

  • B. 描述对象间的相互作用

  • C. 面向对象程序设计

  • D. 确定基于对象的操作

答案与解析

平台答案:C。

整理解析

选 C。分析阶段识别对象、关系、交互和所需操作,形成问题域模型;用具体程序设计语言实现这些对象属于后续编码工作。

题目 059

来源:知识点练习「面向对象技术」第 59 题(原站入口)。

对于下列 UML 状态图,以下哪一种情形不一定使系统退出复合状态 B( )?

题目配图

  • A. 状态B中的两个结束状态均达到

  • B. 在当前状态为B2时,事件e2发生

  • C. 事件e2发生

  • D. 事件e1发生

答案与解析

平台答案:C。

整理解析

选 C。e2 的出发状态是 B2,只有 B2 活跃且该转换可触发时,e2 才沿图中箭头退出 B 到 C3;仅说 e2 发生不足以保证退出。e1 对应从 B 到 C1 的转换;两个正交区域均达到终态时,B 完成并沿无触发器的完成转换到 C2。

题目 060

来源:知识点练习「面向对象技术」第 60 题(原站入口)。

对于 UML 状态图的转换(transition),以下说法哪项不正确( )?

  • A. 活动可以在转换时执行也可以在状态内执行

  • B. 监护条件只有在相应的事件发生时才进行检查

  • C. 一个转换可以有事件触发器、监护条件和一个状态

  • D. 事件触发转换

答案与解析

平台答案:C。

整理解析

选 C。转换标签通常组织为“触发器 [守卫条件] / 效应”,其中不是把“一个状态”作为效应项。纠错:平台用“转换至少有两个状态”论证不成立,自转换的源与目标可以是同一个状态。B应按相应触发被处理时评估守卫来理解;完成转换也可不显式写事件触发器,不能把B、D扩大为所有转换都必须等待外部事件。

题目 061

来源:知识点练习「面向对象技术」第 61 题(原站入口)。

下列①②③④属于 UML 的哪类图(61)?场景要求:一名 Doctor 可治疗多名 Patient,一名 Patient 也可由多名 Doctor 治疗;同一名医生可能多次治疗同一病人,每次 Treatment 要记录日期和时间。图中符合场景的模型是(62)。

题目配图

请作答:第 61 题。

  • A. 用例图

  • B. 对象图

  • C. 类图

  • D. 协作图

答案与解析

平台答案:C。

整理解析

选 C。图中使用 Doctor、Patient、Treatment 等类框,属性、关联及多重度来定义类型结构,属于类图。对象图则表示具体实例在某时刻的连接。

题目 062

来源:知识点练习「面向对象技术」第 62 题(原站入口)。

下列①②③④属于 UML 的哪类图(61)?场景要求:一名 Doctor 可治疗多名 Patient,一名 Patient 也可由多名 Doctor 治疗;同一名医生可能多次治疗同一病人,每次 Treatment 要记录日期和时间。图中符合场景的模型是(62)。

题目配图

请作答:第 62 题。

  • A. ①

  • B. ②

  • C. ③

  • D. ④

答案与解析

平台答案:A。

整理解析

平台答案保留 A(①)。①以两端 、{non-unique} 和带日期时间的 Treatment 关联类表达可重复的医患治疗联系。但②将每次治疗建成独立 Treatment 对象,Doctor、Patient 端均为1,Treatment端均为,同样允许同一医患组合有多次治疗记录。原页已核实,题干只有多对多、多次治疗及记录日期时间这些条件,没有“必须使用关联类”等限制,四幅原图均按题面保留。因此②也符合文字要求,不能把平台①解释为唯一可行模型。

题目 063

来源:知识点练习「面向对象技术」第 63 题(原站入口)。

把一组算法分别封装成可替换的实现,使算法能独立于使用它们的客户变化,这是(63)模式。它适用于以下哪些情况(64)?

①客户需要一组相关对象;②一个对象变化时需改变其他对象;③需要同一算法的不同变体;④多个相关类仅在行为上不同。

请作答:第 63 题。

  • A. 命令(Command)

  • B. 责任链(Chain of Responsibility)

  • C. 观察者(Observer)

  • D. 策略(Strategy)

答案与解析

平台答案:D。

整理解析

选 D。策略模式把变化集中到算法对象,客户经由共同策略接口调用,可以替换算法而少改客户代码。

题目 064

来源:知识点练习「面向对象技术」第 64 题(原站入口)。

把一组算法分别封装成可替换的实现,使算法能独立于使用它们的客户变化,这是(63)模式。它适用于以下哪些情况(64)?

①客户需要一组相关对象;②一个对象变化时需改变其他对象;③需要同一算法的不同变体;④多个相关类仅在行为上不同。

请作答:第 64 题。

  • A. ①②

  • B. ②③

  • C. ③④

  • D. ①④

答案与解析

平台答案:C。

整理解析

选 C,即③④。这两项都把变化集中在可互换的行为或算法上。①更接近相关产品族的创建问题,②更接近变化通知的观察者场景。

题目 065

来源:知识点练习「面向对象技术」第 65 题(原站入口)。

让复杂对象的构建步骤与最终表示分离,从而同一构建过程可产生不同表示的是(65)模式。下列哪些情形适用(66)?

①抽象复杂对象的构建步骤;②由构建过程的具体实现生成复杂对象的不同表示;③一个类只有一个实例;④一个类的实例只取若干状态组合中的一种。

请作答:第 65 题。

  • A. 生成器(Builder)

  • B. 工厂方法(Factory Method)

  • C. 原型(Prototype)

  • D. 单例( Singleton)

答案与解析

平台答案:A。

整理解析

选 A。生成器把步骤的组织与每步如何生产部件分开,由不同具体生成器得到不同产品表示。

题目 066

来源:知识点练习「面向对象技术」第 66 题(原站入口)。

让复杂对象的构建步骤与最终表示分离,从而同一构建过程可产生不同表示的是(65)模式。下列哪些情形适用(66)?

①抽象复杂对象的构建步骤;②由构建过程的具体实现生成复杂对象的不同表示;③一个类只有一个实例;④一个类的实例只取若干状态组合中的一种。

请作答:第 66 题。

  • A. ①②

  • B. ②③

  • C. ③④

  • D. ①④

答案与解析

平台答案:A。

整理解析

选 A,即①②。两项直接对应分离构建步骤与具体表示的目的。③是单例关注的问题,④本身没有说明需要可复用的分步构建过程。

题目 067

来源:知识点练习「面向对象技术」第 67 题(原站入口)。

当一个类有两个或更多超类时,这种继承方式称为(67),它可能使子类中的成员出现(68)。

请作答:第 67 题。

  • A. 多重继承

  • B. 多态

  • C. 封装

  • D. 层次继承

答案与解析

平台答案:A。

整理解析

选 A。一个类同时从多个超类继承,称为多重继承。该题是一般面向对象概念;Java 类仅能直接继承一个类,但可实现多个接口,不能把一般概念当成Java类继承语法。

题目 068

来源:知识点练习「面向对象技术」第 68 题(原站入口)。

当一个类有两个或更多超类时,这种继承方式称为(67),它可能使子类中的成员出现(68)。

请作答:第 68 题。

  • A. 动态

  • B. 私有

  • C. 公共

  • D. 二义性

答案与解析

平台答案:D。

整理解析

选 D。多个父类可能提供同名成员或经不同路径带来同一祖先成员,未有消歧规则时就可能不明确该选择哪一份。题干说的是“可能”,不表示多重继承必然无法解析。

题目 069

来源:知识点练习「面向对象技术」第 69 题(原站入口)。

采用面向对象方法开发软件时,在分析阶段架构师主要关注系统的哪一方面( )?

  • A. 技术

  • B. 部署

  • C. 实现

  • D. 行为

答案与解析

平台答案:D。

整理解析

选 D。分析首先明确系统应完成的行为和业务职责;具体技术、部署方式和代码实现是更偏设计与实现阶段的决策。

题目 070

来源:知识点练习「面向对象技术」第 70 题(原站入口)。

在以下描述中,哪一项体现面向对象的多态( )?

  • A. 客户类无需知道所调用方法的特定子类的实现

  • B. 对象动态地修改类

  • C. 一个对象对应多张数据库表

  • D. 子类只能够覆盖父类中非抽象的方法

答案与解析

平台答案:A。

整理解析

选 A。客户通过共同接口调用操作,由实际对象执行相应子类实现,因此不必了解具体子类的实现细节。多态不要求对象更换自身所属类;抽象方法也可由子类实现,并非只能覆盖非抽象方法。

题目 071

来源:知识点练习「面向对象技术」第 71 题(原站入口)。

判断完整 UML 图的类型(71),并识别两组局部符号:下方按原顺序列出的前两幅小图表示(72),接下来的两幅箭头小图表示(73);最后一幅是对应的完整图。

题目配图

题目配图

题目配图

题目配图

题目配图

请作答:第 71 题。

  • A. 序列图

  • B. 状态图

  • C. 通信图

  • D. 活动图

答案与解析

平台答案:C。

整理解析

选 C。完整图把参与对象布置在连接网络中,以1、1.1、2.1等编号标示消息先后和嵌套层级,重点呈现参与者的连接组织,是通信图。序列图通常另以纵向生命线突出时间顺序。

题目 072

来源:知识点练习「面向对象技术」第 72 题(原站入口)。

判断完整 UML 图的类型(71),并识别两组局部符号:下方按原顺序列出的前两幅小图表示(72),接下来的两幅箭头小图表示(73);最后一幅是对应的完整图。

题目配图

题目配图

题目配图

题目配图

题目配图

请作答:第 72 题。

  • A. 类

  • B. 对象

  • C. 流名称

  • D. 消息

答案与解析

平台答案:B。

整理解析

选 B。前两个框分别为带下划线的 :Order 与 b:Book,表示实例;前者省略对象名,后者给出对象名 b 及所属类 Book。不能把实例所属的类名误读成该框本身在表示类。

题目 073

来源:知识点练习「面向对象技术」第 73 题(原站入口)。

判断完整 UML 图的类型(71),并识别两组局部符号:下方按原顺序列出的前两幅小图表示(72),接下来的两幅箭头小图表示(73);最后一幅是对应的完整图。

题目配图

题目配图

题目配图

题目配图

题目配图

请作答:第 73 题。

  • A. 类

  • B. 对象

  • C. 流名称

  • D. 消息

答案与解析

平台答案:D。

整理解析

选 D。箭头旁的 find_books()、search() 等是对象间发送的消息;编号表达顺序或嵌套层级,* 表示迭代发送。它们不是对象或类的名称。

题目 074

来源:知识点练习「面向对象技术」第 74 题(原站入口)。

下图给出观察者模式的抽象结构。角色(74)掌握已注册的观察者,允许任意多个观察者观察同一目标,并提供注册及删除观察者的接口;本模式最主要体现的特征为(75)。

题目配图

请作答:第 74 题。

  • A. Subject

  • B. Observer

  • C. Concrete Subject

  • D. Concrete Observer

答案与解析

平台答案:A。

整理解析

选 A。图中 Subject 声明 registerObserver、removeObserver 和 notifyObservers,负责主题一侧的订阅管理契约;ConcreteSubject 是其具体实现。图中虚线空心三角表示实现接口,不应当作类之间的普通继承线。

题目 075

来源:知识点练习「面向对象技术」第 75 题(原站入口)。

下图给出观察者模式的抽象结构。角色(74)掌握已注册的观察者,允许任意多个观察者观察同一目标,并提供注册及删除观察者的接口;本模式最主要体现的特征为(75)。

题目配图

请作答:第 75 题。

  • A. 类应该对扩展开放,对修改关闭

  • B. 使所要交互的对象尽量松耦合

  • C. 组合优先于继承使用

  • D. 仅与直接关联类交互

答案与解析

平台答案:B。

整理解析

选 B。主题按 Observer 接口通知,不必依赖每个具体观察者的实现,观察者可独立增减,因此突出松耦合。模式并非没有依赖,而是把依赖限制在稳定契约上。

题目 076

来源:知识点练习「面向对象技术」第 76 题(原站入口)。

装饰器模式与外观模式分别对应以下哪种用途(76)、(77)?

①包装一个对象,提供客户想要的另一种接口;②包装一个对象,为其增加额外行为;③包装一个对象,控制对它的访问;④包装一组对象,简化它们的接口。

请作答:第 76 题。

  • A. ①

  • B. ②

  • C. ③

  • D. ④

答案与解析

平台答案:B。

整理解析

选 B,即②。装饰器的重点是在相容接口下增加行为。①侧重接口适配,③侧重代理访问控制,④侧重外观对多个子系统对象的简化。

题目 077

来源:知识点练习「面向对象技术」第 77 题(原站入口)。

装饰器模式与外观模式分别对应以下哪种用途(76)、(77)?

①包装一个对象,提供客户想要的另一种接口;②包装一个对象,为其增加额外行为;③包装一个对象,控制对它的访问;④包装一组对象,简化它们的接口。

请作答:第 77 题。

  • A. ①

  • B. ②

  • C. ③

  • D. ④

答案与解析

平台答案:D。

整理解析

选 D,即④。外观提供较高层的简洁入口来协调子系统对象。纠错:经典外观模式不强制所有客户都只能经该入口,仍可让有特殊需求的客户直接使用子系统;平台将“统一入口”表述为必须经过,限定过强。

题目 078

来源:知识点练习「面向对象技术」第 78 题(原站入口)。

把逻辑相关的数据和行为组合在一起,并向使用者隐藏内部信息,称为(78)。如果类的属性或方法被声明为 private,那么(79)可以访问它们。

请作答:第 78 题。

  • A. 抽象

  • B. 继承

  • C. 封装

  • D. 多态

答案与解析

平台答案:C。

整理解析

选 C。封装把状态与操作放入统一边界,并通过访问控制隐藏实现细节,外部代码只依赖对外接口。

题目 079

来源:知识点练习「面向对象技术」第 79 题(原站入口)。

把逻辑相关的数据和行为组合在一起,并向使用者隐藏内部信息,称为(78)。如果类的属性或方法被声明为 private,那么(79)可以访问它们。

请作答:第 79 题。

  • A. 应用程序中所有方法

  • B. 只有此类中定义的方法

  • C. 只有此类中定义的public方法

  • D. 同一个包中的类中定义的方法

答案与解析

平台答案:B。

整理解析

按教材的基本访问控制模型选 B。private 的访问权取决于声明范围,不取决于调用方法自己是否为 public;同包的普通其他类也不会自动获得访问权。语言限定:Java 同一顶层类范围内的嵌套类型之间可访问私有成员,C++ 还可显式授权友元,因此“只有此类方法”是本题的简化口径,不能不加条件地推广到所有语言。

题目 080

来源:知识点练习「面向对象技术」第 80 题(原站入口)。

利用继承创建子类后,以下哪项正确描述子类可具有的内容( )?

  • A. 只能有父类中的属性

  • B. 只能有父类中的行为

  • C. 只能新增行为

  • D. 可以有新的属性和行为

答案与解析

平台答案:D。

整理解析

选 D。子类可在继承特征的基础上增加属性和操作,以表达更具体的概念;继承并不把扩展限制为只能增加行为。

题目 081

来源:知识点练习「面向对象技术」第 81 题(原站入口)。

进行面向对象分析时,常从需求文字中的哪类短语入手识别候选对象( )?

  • A. 动词短语

  • B. 名词短语

  • C. 形容词

  • D. 副词

答案与解析

平台答案:B。

整理解析

选 B。名词短语常指向问题域中的实体或概念,可作为候选对象/类;动词短语更常提示职责与操作。这只是识别线索,仍需剔除重复、范围外概念及仅应建成属性的名词。

题目 082

来源:知识点练习「面向对象技术」第 82 题(原站入口)。

阅读下列 UML 类图:Shop 与 Magazine 的关系为(82),Magazine 与 Page 的关系为(83)。以下哪一项通常不使用 UML 类图建模(84)?

题目配图

请作答:第 82 题。

  • A. 关联

  • B. 依赖

  • C. 组合

  • D. 继承

答案与解析

平台答案:A。

整理解析

选 A。Shop 与 Magazine 之间是标有 sells 的普通实线关联;Magazine 端的 * 表示一个 Shop 可关联多个 Magazine,符号本身包含零个的可能。这里没有泛化三角、依赖虚线或组合菱形。

题目 083

来源:知识点练习「面向对象技术」第 83 题(原站入口)。

阅读下列 UML 类图:Shop 与 Magazine 的关系为(82),Magazine 与 Page 的关系为(83)。以下哪一项通常不使用 UML 类图建模(84)?

题目配图

请作答:第 83 题。

  • A. 关联

  • B. 依赖

  • C. 组合

  • D. 继承

答案与解析

平台答案:C。

整理解析

选 C。Magazine 端的实心菱形表示组合,Magazine 是整体,Page 是部分;Page 端的 * 描述每本杂志关联的页数范围。组合强调部分在同一时刻至多属于一个组合整体,不能把菱形方向读反。

题目 084

来源:知识点练习「面向对象技术」第 84 题(原站入口)。

阅读下列 UML 类图:Shop 与 Magazine 的关系为(82),Magazine 与 Page 的关系为(83)。以下哪一项通常不使用 UML 类图建模(84)?

题目配图

请作答:第 84 题。

  • A. 系统的词汇

  • B. 简单的协作

  • C. 逻辑数据库模式

  • D. 对象快照

答案与解析

平台答案:D。

整理解析

选 D。对象快照记录具体实例及当时的链接,通常使用对象图;类图表达类及其关系,可用于领域词汇、参与协作的静态结构和逻辑数据模式。

题目 085

来源:知识点练习「面向对象技术」第 85 题(原站入口)。

自动售货机在收款并接受商品选择后,依库存、已存货币量、找零能力和所选项目等情况,可表现为:交付商品但不找零;交付商品并找零;金额不足不交付;库存不足不交付。适合用(85)模式实现。下图中(86)是客户使用的主要接口,可由不同状态配置;该模式的分类为(87),主要意图为(88)。

题目配图

请作答:第 85 题。

  • A. 观察者(Observer)

  • B. 状态(State)

  • C. 策略(Strategy)

  • D. 访问者(Visitor)

答案与解析

平台答案:B。

整理解析

选 B。相同的购买请求会因库存、金额等内部状态不同而产生不同处理,图中 Buy 又通过状态抽象委托 handle,符合状态模式。判断依据是状态影响行为的职责安排,不能仅凭类名包含 State 就得出结论。

题目 086

来源:知识点练习「面向对象技术」第 86 题(原站入口)。

自动售货机在收款并接受商品选择后,依库存、已存货币量、找零能力和所选项目等情况,可表现为:交付商品但不找零;交付商品并找零;金额不足不交付;库存不足不交付。适合用(85)模式实现。下图中(86)是客户使用的主要接口,可由不同状态配置;该模式的分类为(87),主要意图为(88)。

题目配图

请作答:第 86 题。

  • A. Vending Machine State

  • B. Buy

  • C. Vending Deposit State

  • D. Vending Stock State

答案与解析

平台答案:B。

整理解析

选 B。Buy 扮演上下文角色,是客户发起购买操作的入口,并关联当前的 Vending Machine State;客户不必直接选择每个具体状态类。题干“接口”指对客户的使用入口,不意味着 Buy 必须声明成 Java interface 或 UML 接口分类器。

题目 087

来源:知识点练习「面向对象技术」第 87 题(原站入口)。

自动售货机在收款并接受商品选择后,依库存、已存货币量、找零能力和所选项目等情况,可表现为:交付商品但不找零;交付商品并找零;金额不足不交付;库存不足不交付。适合用(85)模式实现。下图中(86)是客户使用的主要接口,可由不同状态配置;该模式的分类为(87),主要意图为(88)。

题目配图

请作答:第 87 题。

  • A. 创建型对象模式

  • B. 结构型对象模式

  • C. 行为型类模式

  • D. 行为型对象模式

答案与解析

平台答案:D。

整理解析

选 D。状态模式通过上下文与当前状态对象的协作分配行为,属于行为型对象模式。虽使用了状态类型层次,分类关键仍是对象之间的委托,而不是只靠继承固定流程。

题目 088

来源:知识点练习「面向对象技术」第 88 题(原站入口)。

自动售货机在收款并接受商品选择后,依库存、已存货币量、找零能力和所选项目等情况,可表现为:交付商品但不找零;交付商品并找零;金额不足不交付;库存不足不交付。适合用(85)模式实现。下图中(86)是客户使用的主要接口,可由不同状态配置;该模式的分类为(87),主要意图为(88)。

题目配图

请作答:第 88 题。

  • A. 当一个对象状态改变时所有依赖它的对象得到通知并自动更新

  • B. 在不破坏封装性的前提下,捕获对象的内部状态并在对象之外保存

  • C. 一个对象在其内部状态改变时改变其行为

  • D. 将请求封装为对象从而可以使用不同的请求对客户进行参数化

答案与解析

平台答案:C。

整理解析

选 C。状态模式使行为随内部状态变化。A是观察者的变化通知,B是备忘录的状态保存,D是命令的请求封装;名称里含“状态”并不使备忘录等同状态模式。

题目 089

来源:知识点练习「面向对象技术」第 89 题(原站入口)。

对象的哪一方面同时描述其全部属性(题干称通常是静态的)和这些属性的当前取值(题干称通常是动态的)( )?

  • A. 状态

  • B. 唯一ID

  • C. 行为

  • D. 语义

答案与解析

平台答案:A。

整理解析

选 A。状态由对象在某时刻的属性取值刻画。这里“属性通常静态”指属性结构相对稳定,不是说属性必须声明为 static;当前值也可以不变。平台将广泛的“对象语义”直接等同于共享资源的指针/引用语义,范围过窄,不能作为通用定义。

题目 090

来源:知识点练习「面向对象技术」第 90 题(原站入口)。

把一次过程调用与执行该调用所需的代码在运行时连接,称为(90);若在编译时完成这种连接,则称为(91)。

请作答:第 90 题。

  • A. 消息传递

  • B. 类型检查

  • C. 静态绑定

  • D. 动态绑定

答案与解析

平台答案:D。

整理解析

选 D。运行时才选择要执行的方法实现是动态绑定;编译期确定则是静态绑定。本问回答第90空;第91空属于同一材料的另一个小问。

题目 091

来源:知识点练习「面向对象技术」第 91 题(原站入口)。

将过程调用与响应调用所需执行的代码建立联系:第90空指在运行时完成这种结合的机制,第91空指在编译时完成结合的机制。本题回答第91空。

  • A. 消息传递

  • B. 类型检查

  • C. 静态绑定

  • D. 动态绑定

答案与解析

平台答案:C。

整理解析

选C。编译时确定调用所对应的实现称为静态绑定;运行时才确定则称动态绑定。消息传递描述对象之间的操作请求,类型检查验证类型约束,两者都不等同于绑定时机。平台把消息传递只解释为并行机之间的消息包通信,范围过窄。

题目 092

来源:知识点练习「面向对象技术」第 92 题(原站入口)。

不同类拥有共同的超类;同一条消息可以触发这些类的不同对象所实现的方法。这体现了哪种现象?

  • A. 类型转换

  • B. 映射

  • C. 单态

  • D. 多态

答案与解析

平台答案:D。

整理解析

选D。多态使同一操作请求根据对象的具体类型产生不同实现。平台把“同一对象收到不同消息”也直接算作多态并不充分;它将单态解释为只有一个实例,也混淆了单态与单例。

题目 093

来源:知识点练习「面向对象技术」第 93 题(原站入口)。

下图描述汽车导航系统。第93空判断UML图的类型,第94空选择该图所展示的内容,第95空选择Mapping对象获取汽车当前位置(GPS Location)所用的消息。

汽车导航系统UML图

本题回答第93空:这是哪类UML图?

  • A. 类图

  • B. 组件图

  • C. 通信图

  • D. 部署图

答案与解析

平台答案:C。

整理解析

选C。图中对象由连接线组织,消息用1、1.1、2、2.1等编号表示调用次序,属于通信图。它强调参与交互的对象及连接,没有顺序图典型的纵向生命线。

题目 094

来源:知识点练习「面向对象技术」第 94 题(原站入口)。

下图描述汽车导航系统。第93空判断UML图的类型,第94空选择该图所展示的内容,第95空选择Mapping对象获取汽车当前位置(GPS Location)所用的消息。

汽车导航系统UML图

本题回答第94空:此图主要展示什么?

  • A. 对象之间的消息流及其顺序

  • B. 完成任务所进行的活动流

  • C. 对象的状态转换及其事件顺序

  • D. 对象之间消息的时间顺序

答案与解析

平台答案:A。

整理解析

按本题对图的侧重点划分选A,通信图展示对象之间的消息流及其顺序,并强调对象间的组织关系。它同样能用编号表示消息次序,因此不能说它完全不表达时间先后;D更接近顺序图的典型描述。

题目 095

来源:知识点练习「面向对象技术」第 95 题(原站入口)。

下图描述汽车导航系统。第93空判断UML图的类型,第94空选择该图所展示的内容,第95空选择Mapping对象获取汽车当前位置(GPS Location)所用的消息。

汽车导航系统UML图

本题回答第95空:Mapping获取汽车当前位置用哪条消息?

  • A. 1: getGraphic()

  • B. 2: getCarPos()

  • C. 1.1: CurrentArea()

  • D. 2.1: getCarLocation()

答案与解析

平台答案:D。

整理解析

选D。图中Mapping指向GPS location的消息标为2.1: getCarLocation();2: getCarPos()是UI发给Mapping的外层请求。嵌套编号2.1表示处理消息2时进一步发出的调用。

题目 096

来源:知识点练习「面向对象技术」第 96 题(原站入口)。

设计一个Web应用框架,可生成博客、新闻网站、网上商店等具体应用,并让每种应用选用浅色或深色等主题。类图如下:第96空选择设计模式;第97空选择供客户程序使用、且保存主题类型引用的主要接口;第98空选择模式类别;第99空选择其主要意图。

Web应用与主题类图

本题回答第96空:适合采用哪种模式?

  • A. 观察者(Observer)

  • B. 访问者(Ⅴisitor)

  • C. 策略(Strategy)

  • D. 桥接(Bridge)

答案与解析

平台答案:D。

整理解析

选D。Web应用类型与主题是两个可独立扩展的维度,WebApplication通过Theme引用把它们组合起来,符合桥接模式。新增应用或主题无需为两者的每种组合都建立一个子类。

题目 097

来源:知识点练习「面向对象技术」第 97 题(原站入口)。

设计一个Web应用框架,可生成博客、新闻网站、网上商店等具体应用,并让每种应用选用浅色或深色等主题。类图如下:第96空选择设计模式;第97空选择供客户程序使用、且保存主题类型引用的主要接口;第98空选择模式类别;第99空选择其主要意图。

Web应用与主题类图

本题回答第97空:哪个接口供客户使用并持有主题引用?

  • A. WebApplication

  • B. Blog

  • C. Theme

  • D. Light

答案与解析

平台答案:A。

整理解析

选A。图中的WebApplication位于应用抽象层,既是Blog、Store、News Site的共同抽象,又通过关联保存Theme引用。Theme是实现主题功能的一侧,Light是其具体实现。

题目 098

来源:知识点练习「面向对象技术」第 98 题(原站入口)。

设计一个Web应用框架,可生成博客、新闻网站、网上商店等具体应用,并让每种应用选用浅色或深色等主题。类图如下:第96空选择设计模式;第97空选择供客户程序使用、且保存主题类型引用的主要接口;第98空选择模式类别;第99空选择其主要意图。

Web应用与主题类图

本题回答第98空:该模式属于哪一类别?

  • A. 创建型对象模式

  • B. 结构型对象模式

  • C. 行为型类模式

  • D. 行为型对象模式

答案与解析

平台答案:B。

整理解析

选B。桥接以对象组合连接抽象层和实现层,属于结构型对象模式;其核心是组织协作结构,而不是规定创建过程或一套算法行为。

题目 099

来源:知识点练习「面向对象技术」第 99 题(原站入口)。

设计一个Web应用框架,可生成博客、新闻网站、网上商店等具体应用,并让每种应用选用浅色或深色等主题。类图如下:第96空选择设计模式;第97空选择供客户程序使用、且保存主题类型引用的主要接口;第98空选择模式类别;第99空选择其主要意图。

Web应用与主题类图

本题回答第99空:该模式的主要意图是什么?

  • A. 将抽象部分与其实现部分分离,使它们都可以独立地变化

  • B. 动态地给一个对象添加一些额外的职责

  • C. 为其他对象提供一种代理以控制对这个对象的访问

  • D. 将一个类的接口转换成客户希望的另外一个接口

答案与解析

平台答案:A。

整理解析

选A。应用抽象与主题实现分别变化,通过引用协作。B对应装饰,C对应代理,D对应适配器,均不是本例两个维度独立扩展的主要意图。

题目 100

来源:知识点练习「面向对象技术」第 100 题(原站入口)。

面向对象方法中的继承主要用于什么?

  • A. 在已存在的类的基础上创建新类

  • B. 在已存在的类中添加新的方法

  • C. 在已存在的类中添加新的属性

  • D. 在已存在的状态中添加新的状态

答案与解析

平台答案:A。

整理解析

选A。继承在已有类的基础上定义新类,使派生类获得并可扩展基类的特征。平台把B、C直接称为封装、D称为多态不成立:给现有类增加成员或增加状态,本身不足以定义这些机制。

题目 101

来源:知识点练习「面向对象技术」第 101、136 题(原站入口)。

操作或方法使用相同名称,但在不同上下文中具有不同含义,这称为什么多态?

  • A. 参数

  • B. 包含

  • C. 过载

  • D. 强制

答案与解析

平台答案(来源第 101 题):C。

整理解析(来源第 101 题)

选C,即过载多态,例如同名方法按参数类型或数量区分。参数多态用统一定义处理多种类型,包含多态依靠子类型关系,强制多态涉及类型转换。平台称包含多态一般需要运行时类型检查不严谨;动态派发与运行时类型检查不是一回事。

来源第 136 题对照

原题题干

哪一种多态允许同一个名称在不同上下文中具有不同含义?( )

原题选项对照

原选项内容本页选项
A

参数

A
B

包含

B
C

过载

C
D

强制

D

原平台答案(来源第 136 题,原题选项):C;对应本页选项:C;本页平台答案:C。

整理解析(来源第 136 题)

同名函数或运算符随参数类型、个数等上下文具有不同含义,属于过载多态,选C。参数多态使用类型参数,包含多态基于子类型替换,强制多态涉及类型转换。平台所称“包含多态一般需要运行时类型检查”不宜作为定义;动态分派与运行时类型检查是不同机制。

题目 102

来源:知识点练习「面向对象技术」第 102 题(原站入口)。

某销售系统支持客户扫描二维码付款。采用面向对象方法建模时,第102空判断客户类的类别,第103空判断二维码类的类别。

本题回答第102空:客户类属于哪一类?

  • A. 接口

  • B. 实体

  • C. 控制

  • D. 状态

答案与解析

平台答案:B。

整理解析

选B。客户类表示系统需要管理的业务对象及其信息,按实体—边界—控制的分析分类属于实体类。它与作为系统外部参与者的具体客户不是同一建模角色。

题目 103

来源:知识点练习「面向对象技术」第 103 题(原站入口)。

某销售系统支持客户扫描二维码付款。采用面向对象方法建模时,第102空判断客户类的类别,第103空判断二维码类的类别。

本题回答第103空:二维码类属于哪一类?

  • A. 接口

  • B. 实体

  • C. 控制

  • D. 状态

答案与解析

平台答案:A。

整理解析

按题目将二维码视为付款交互入口的设定,选A,即接口类或边界类。这里按承担的交互职责分类,并不意味着任何保存二维码数据的类都必然是边界类。

题目 104

来源:知识点练习「面向对象技术」第 104 题(原站入口)。

观察下方UML图:第104空判断图的类型,第105空选择图所表达的内容,第106空依次判断标号①、②所示接口的种类。

带接口标记的UML图

本题回答第104空:这是哪一种UML图?

  • A. 类图

  • B. 组件图

  • C. 通信图

  • D. 部署图

答案与解析

平台答案:B。

整理解析

选B。各方框带有组件标识,并以供接口、需接口及依赖连接协作,表示组件图。它没有部署图所强调的设备节点和执行环境。

题目 105

来源:知识点练习「面向对象技术」第 105 题(原站入口)。

观察下方UML图:第104空判断图的类型,第105空选择图所表达的内容,第106空依次判断标号①、②所示接口的种类。

带接口标记的UML图

本题回答第105空:这类图主要展示什么?

  • A. 一组对象、接口、协作和它们之间的关系

  • B. 收发消息的对象的结构组织

  • C. 组件之间的组织和依赖

  • D. 面向对象系统的物理模型

答案与解析

平台答案:C。

整理解析

选C。图中Order System依赖Customer Repository与Inventory System提供的接口,表达组件之间的组织和依赖。共享平台解析末尾写“选择B”是前一小问的结论,不能套用到本问;平台将类图概括为一组对象也不准确,类图主要描述类及其关系。

题目 106

来源:知识点练习「面向对象技术」第 106 题(原站入口)。

观察下方UML图:第104空判断图的类型,第105空选择图所表达的内容,第106空依次判断标号①、②所示接口的种类。

带接口标记的UML图

本题回答第106空:①、②分别是哪类接口?

  • A. 供接口和供接口

  • B. 需接口和需接口

  • C. 供接口和需接口

  • D. 需接口和供接口

答案与解析

平台答案:D。

整理解析

选D。①指向半圆形插口,表示需接口;②指向圆形标记,表示供接口。依赖方需要服务,提供方通过供接口承诺服务。共享平台解析末尾的“选择B”不适用于本问,应保留本问平台答案D。

题目 107

来源:知识点练习「面向对象技术」第 107 题(原站入口)。

超市销售系统中,顾客把毛巾、饼干、酸奶等Item放入Shopping_Cart;Checkout通过Manual或Auto方式逐项累计价格并结账。下图省略方法。第107空选择设计模式;第108空选择声明accept(Checkout)并由子类实现该操作的类;第109空判断模式类别;第110空选择适用场景。

超市物品与收银类图

本题回答第107空:采用了哪种模式?

  • A. 观察者(Observer)

  • B. 访问者(Visitor)

  • C. 策略(Strategy)

  • D. 桥接器(Bridge)

答案与解析

平台答案:B。

整理解析

选B。Item接收Checkout访问者,具体物品通过accept把与自身类型有关的结算操作交给访问者,符合访问者模式。平台称桥接体现整体—部分关系、策略只能被一个对象调用,均不能作为判别依据:桥接分离变化维度,策略也可被多个上下文使用。

题目 108

来源:知识点练习「面向对象技术」第 108 题(原站入口)。

超市销售系统中,顾客把毛巾、饼干、酸奶等Item放入Shopping_Cart;Checkout通过Manual或Auto方式逐项累计价格并结账。下图省略方法。第107空选择设计模式;第108空选择声明accept(Checkout)并由子类实现该操作的类;第109空判断模式类别;第110空选择适用场景。

超市物品与收银类图

本题回答第108空:哪个类声明accept操作?

  • A. Item

  • B. Shopping_Cart

  • C. Checkout

  • D. Manual和Auto

答案与解析

平台答案:A。

整理解析

选A。Item是元素的共同抽象,声明接收Checkout访问者的accept操作;Towel、Cookie、Yogurt分别实现它。Shopping_Cart保存元素集合,Checkout一侧承担访问操作。

题目 109

来源:知识点练习「面向对象技术」第 109 题(原站入口)。

超市销售系统中,顾客把毛巾、饼干、酸奶等Item放入Shopping_Cart;Checkout通过Manual或Auto方式逐项累计价格并结账。下图省略方法。第107空选择设计模式;第108空选择声明accept(Checkout)并由子类实现该操作的类;第109空判断模式类别;第110空选择适用场景。

超市物品与收银类图

本题回答第109空:该模式属于哪一类别?

  • A. 创建型对象模式

  • B. 结构型对象模式

  • C. 行为型类模式

  • D. 行为型对象模式

答案与解析

平台答案:D。

整理解析

选D。访问者把作用于对象结构中各元素的操作分配给访问者对象,属于行为型对象模式,关注对象之间如何协作完成操作。

题目 110

来源:知识点练习「面向对象技术」第 110 题(原站入口)。

超市销售系统中,顾客把毛巾、饼干、酸奶等Item放入Shopping_Cart;Checkout通过Manual或Auto方式逐项累计价格并结账。下图省略方法。第107空选择设计模式;第108空选择声明accept(Checkout)并由子类实现该操作的类;第109空判断模式类别;第110空选择适用场景。

超市物品与收银类图

本题回答第110空:该模式适用于哪种情况?

  • A. 必须保存一个对象在某一个时刻的(部分)状态

  • B. 想在不明确指定接收者的情况下向多个对象中的一个提交一个请求

  • C. 需要对一个对象结构中的对象进行很多不同的并且不相关的操作

  • D. 在不同的时刻指定、排列和执行请求

答案与解析

平台答案:C。

整理解析

选C。当元素类型相对稳定,却需要不断增加不同操作时,可把各操作组织成访问者,减少对元素类的反复修改。A是备忘录的用途,B对应责任链,D对应命令。

题目 112

来源:知识点练习「面向对象技术」第 112 题(原站入口)。

用面向对象方法开发软件,并将汽车视为一个系统。下列哪组对象之间不属于组成(Composition)关系?

  • A. 汽车和座位

  • B. 汽车和车窗

  • C. 汽车和发动机

  • D. 汽车和音乐系统

答案与解析

平台答案:D。

整理解析

平台答案为D,按其把音乐系统视为可独立使用的外部系统来理解。但仅凭“汽车与某部件”的名称不能唯一判断UML组合关系;座位、发动机也可拆换。组合关注模型中的排他整体所有权和生命周期责任,题干没有明确这些约束,平台所作区分依赖额外建模假设。

题目 113

来源:知识点练习「面向对象技术」第 113 题(原站入口)。

面向对象设计要求一个类仅有一个引起变化的原因。这是哪项设计原则?

  • A. 单一责任

  • B. 开放-封闭

  • C. 接口分离

  • D. 里氏替换

答案与解析

平台答案:A。

整理解析

选A,即单一责任(单一职责)原则。应把因不同职责而变化的代码分开;它不等于一个类只能有一个方法,而是让类的变化原因保持内聚。

题目 114

来源:知识点练习「面向对象技术」第 114 题(原站入口)。

所谓聚合对象,是指具有哪种特点的对象?

  • A. 只有静态方法

  • B. 只有基本类型的属性

  • C. 包含其他对象

  • D. 只包含基本类型的属性和实例方法

答案与解析

平台答案:C。

整理解析

选C。聚合对象由其他对象组成,强调对象的组合结构,与是否只有静态方法、基本类型属性无关。此处的“包含”是组合概念,不能把任何普通对象引用都自动认定为UML聚合关系。

题目 115

来源:知识点练习「面向对象技术」第 115 题(原站入口)。

在UML中,哪类图用来表示交付系统的软件组件与硬件之间的物理关系?

  • A. 类

  • B. 组件

  • C. 通信

  • D. 部署

答案与解析

平台答案:D。

整理解析

选D。部署图描述设备、执行环境等节点,以及软件制品在节点上的部署和通信联系。组件图主要描述逻辑组件及依赖。平台把类图说成一组对象不准确,类图主要表示类,实例结构通常用对象图。

题目 116

来源:知识点练习「面向对象技术」第 116 题(原站入口)。

观察下图:第116空判断UML图的种类,第117空选择它展示的系统行为范围。

学生成绩打印示意图

本题回答第116空:图的具体类型是什么?

  • A. 用例图

  • B. 活动图

  • C. 序列图

  • D. 交互图

答案与解析

平台答案:C。

整理解析

选C。图中有纵向生命线、激活条及按时间顺序排列的消息,还包含loop片段,是序列图。序列图本身也属于交互图,所以D是上位类别而不是与C互斥的另一种图;单选按最具体名称取C。

题目 117

来源:知识点练习「面向对象技术」第 117 题(原站入口)。

观察下图:第116空判断UML图的种类,第117空选择它展示的系统行为范围。

学生成绩打印示意图

本题回答第117空:图展示哪种行为范围?

  • A. 一个用例和一个对象的行为

  • B. 一个用例和多个对象的行为

  • C. 多个用例和一个对象的行为

  • D. 多个用例和多个对象的行为

答案与解析

平台答案:B。

整理解析

按题目把成绩生成与打印看作一个用例场景,选B。学生信息页、TranscriptBuilder、Student、Seminar及打印机等多个对象协作完成该场景。但UML并不规定任何序列图都只能对应一个完整用例,也可描述用例片段或更复杂的交互。

题目 118

来源:知识点练习「面向对象技术」第 118 题(原站入口)。

第118空所指的模式把多个有机会处理请求的对象连接成链,请求沿链转发直到被处理,以降低发送者对具体接收者的依赖。第119空所指的模式按顺序访问聚合对象的各个元素,而不暴露内部表示。第120空选择这两种模式共同所属的类别。

本题回答第118空:沿处理对象链转发请求的是哪种模式?

  • A. 责任链(Chain of Responsibility)

  • B. 解释器(Interpreter)

  • C. 命令(Command)

  • D. 迭代器(Iterator)

答案与解析

平台答案:A。

整理解析

选A。责任链把候选处理者串联,请求方不必指定最终由谁处理。它降低直接耦合,但不保证任何请求一定被某个节点接受,链尾的未处理情况仍需设计。

题目 119

来源:知识点练习「面向对象技术」第 119 题(原站入口)。

第118空所指的模式把多个有机会处理请求的对象连接成链,请求沿链转发直到被处理,以降低发送者对具体接收者的依赖。第119空所指的模式按顺序访问聚合对象的各个元素,而不暴露内部表示。第120空选择这两种模式共同所属的类别。

本题回答第119空:不暴露内部表示而遍历元素的是哪种模式?

  • A. 责任链(Chain of Responsibility)

  • B. 解释器(Interpreter)

  • C. 命令(Command)

  • D. 迭代器(Iterator)

答案与解析

平台答案:D。

整理解析

选D。迭代器把遍历位置和推进操作封装在迭代对象中,客户端通过统一方式访问集合,而无需知道集合内部采用数组还是链表等结构。

题目 120

来源:知识点练习「面向对象技术」第 120 题(原站入口)。

第118空所指的模式把多个有机会处理请求的对象连接成链,请求沿链转发直到被处理,以降低发送者对具体接收者的依赖。第119空所指的模式按顺序访问聚合对象的各个元素,而不暴露内部表示。第120空选择这两种模式共同所属的类别。

本题回答第120空:这两种模式共同属于什么类别?

  • A. 创建型对象模式

  • B. 结构型对象模式

  • C. 行为型对象模式

  • D. 行为型类模式

答案与解析

平台答案:C。

整理解析

选C。责任链组织处理对象间的请求传递,迭代器组织集合元素的访问过程,二者都通过对象协作分配行为,属于行为型对象模式。

题目 121

来源:知识点练习「面向对象技术」第 121 题(原站入口)。

观察者(Observer)模式适用于下列哪种需求?

  • A. 访问一个聚合对象的内容而无须暴露它的内部表示

  • B. 减少多个对象或类之间的通信复杂性

  • C. 将对象的状态恢复到先前的状态

  • D. 一对多对象依赖关系,当一个对象修改后,依赖它的对象都自动得到通知

答案与解析

平台答案:D。

整理解析

选D。主题状态变化时,通知依赖它的多个观察者,是一对多的通知关系。A对应迭代器,B对应中介者,C对应备忘录。

题目 122

来源:知识点练习「面向对象技术」第 122 题(原站入口)。

类中的成员变量与成员函数,有时分别称为什么?

  • A. 属性和活动

  • B. 值和方法

  • C. 数据和活动

  • D. 属性和方法

答案与解析

平台答案:D。

整理解析

选D。成员变量描述属性或状态,成员函数定义可执行的方法。变量保存的值是某一时刻的具体数据,不等于属性这个结构概念。

题目 123

来源:知识点练习「面向对象技术」第 123 题(原站入口)。

采用面向对象方法开发系统时,下列哪组对象之间的关系需要建立新类来表示?

  • A. 汽车和座位

  • B. 主人和宠物

  • C. 医生和病人

  • D. 部门和员工

答案与解析

平台答案:C。

整理解析

平台答案为C,通常用就诊等关联对象连接医生与病人。但题干未给出关联需要保存哪些信息,仅凭多对多关系并不能断言UML必须新增类;关联类通常用于给联系本身增加属性或行为。主人与宠物的多重性也取决于业务规则,平台借用关系数据库映射规则作为必然建类依据不充分。

题目 124

来源:知识点练习「面向对象技术」第 124 题(原站入口)。

面向对象设计要求类、模块、函数等软件实体可以扩展,而已有实现应对修改保持封闭。这是哪项原则?

  • A. 共同重用

  • B. 开放封闭

  • C. 接口分离

  • D. 共同封闭

答案与解析

平台答案:B。

整理解析

选B,即开放封闭原则:优先通过扩展增加行为,减少修改稳定代码,并非禁止修复错误。平台在解释接口分离时又加入“依赖抽象、不依赖具体”的描述,混入了依赖倒置原则;接口分离重点是客户不依赖不需要的接口。

题目 125

来源:知识点练习「面向对象技术」第 125 题(原站入口)。

在运行时才把过程调用与响应调用所需执行的代码结合起来,称为什么绑定?

  • A. 动态

  • B. 过载

  • C. 静态

  • D. 参数

答案与解析

平台答案:A。

整理解析

选A。动态绑定根据运行时接收对象等信息确定调用的实现;静态绑定在运行前即可确定。平台把“参数或返回值不同”都当作重载条件不能普遍成立,例如Java、C++不能仅靠不同返回类型重载。

题目 126

来源:知识点练习「面向对象技术」第 126 题(原站入口)。

关于UML状态图,下列哪项说法不正确?

  • A. 活动可以在状态内执行,也可以在迁移时执行

  • B. 若事件触发一个没有特定监护条件的迁移,则对象离开当前状态

  • C. 迁移可以包含事件触发器、监护条件和状态

  • D. 事件触发迁移

答案与解析

平台答案:C。

整理解析

平台答案为C,按迁移标签的常见格式,应写“触发事件[监护条件]/效果(动作)”,而不是把状态当作标签要素。但迁移本身确有源状态和目标状态,平台解析先承认这一点又判C错,表述不自洽;题干的“包含”也不够精确。B还需限定为实际发生的外部迁移,内部迁移并不退出状态,事件发生也不保证一定迁移。

题目 127

来源:知识点练习「面向对象技术」第 127 题(原站入口)。

观察下图:第127空判断UML图的类型,第128空选择对图的描述中不正确的一项。

A与B的关系及多重性

本题回答第127空:这是什么图?

  • A. 对象图

  • B. 类图

  • C. 组件图

  • D. 部署图

答案与解析

平台答案:B。

整理解析

选B。图中A、B是类,连线表示组合关系及多重性,B还有自关联,属于类图。实例图通常使用带下划线的实例标识;平台仅用是否有冒号区分对象图和类图不够可靠。

题目 128

来源:知识点练习「面向对象技术」第 128 题(原站入口)。

观察下图:第127空判断UML图的类型,第128空选择对图的描述中不正确的一项。

A与B的关系及多重性

本题回答第128空:哪项描述不正确?

  • A. 如果B的一个实例被删除,所有包含A的实例都被删除

  • B. A的一个实例可以与B的一个实例关联

  • C. B的一个实例被唯一的一个A的实例所包含

  • D. B的一个实例可与B的另外两个实例关联

答案与解析

平台答案:A。

整理解析

选A。实心菱形位于A端,A是整体、B是部分;删除一个B不要求删除A。A端多重性1表示每个B属于一个A,B端*允许一个A包含多个B。B的自关联两端均为1,两个角色可分别连接其他B。组合删除规则针对整体仍拥有的部分,不能把删除方向反过来。

题目 129

来源:知识点练习「面向对象技术」第 129 题(原站入口)。

某公司开发绘图软件,要求不同绘图程序能够绘制不同图形,且新的图形和绘图程序都可持续增加。题干以绘制直线和图形为例给出下图。第129空选择将抽象与实现分离、使二者独立变化的模式;第130空选择定义实现类接口的类;第131空选择适用情况;第132空判断模式类别。

图形与绘图程序的类图

本题回答第129空:采用哪种模式?

  • A. 适配器(Adapter)

  • B. 装饰(Decorator)

  • C. 桥接(Bridge)

  • D. 组合(Composite)

答案与解析

平台答案:C。

整理解析

选C。图形抽象与绘图实现分别形成变化维度,符合桥接模式。图中的Shape—Drawing箭头画向Shape;若将其理解为标准桥接的导航引用,方向不妥,通常应由Shape持有Drawing引用。应结合题干意图判断,不把不规范箭头照搬为模式定义。

题目 130

来源:知识点练习「面向对象技术」第 130 题(原站入口)。

某公司开发绘图软件,要求不同绘图程序能够绘制不同图形,且新的图形和绘图程序都可持续增加。题干以绘制直线和图形为例给出下图。第129空选择将抽象与实现分离、使二者独立变化的模式;第130空选择定义实现类接口的类;第131空选择适用情况;第132空判断模式类别。

图形与绘图程序的类图

本题回答第130空:哪个类定义实现类接口?

  • A. Shape

  • B. Circle和Rectangle

  • C. V1Drawing和V2Drawing

  • D. Drawing

答案与解析

平台答案:D。

整理解析

选D。Drawing声明绘线、绘圆等底层操作,V1Drawing、V2Drawing实现这些操作;Shape是面向客户的图形抽象。桥接的抽象接口与实现接口不要求完全相同。

题目 131

来源:知识点练习「面向对象技术」第 131 题(原站入口)。

某公司开发绘图软件,要求不同绘图程序能够绘制不同图形,且新的图形和绘图程序都可持续增加。题干以绘制直线和图形为例给出下图。第129空选择将抽象与实现分离、使二者独立变化的模式;第130空选择定义实现类接口的类;第131空选择适用情况;第132空判断模式类别。

图形与绘图程序的类图

本题回答第131空:该模式适用于哪种情况?

  • A. 不希望在抽象和它的实现部分之间有一个固定判定关系

  • B. 想表示对象的部分-整体层次结构

  • C. 想使用一个已经存在的类,而它的接口不符合要求

  • D. 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责

答案与解析

平台答案:A。

整理解析

选A。桥接适合避免抽象与某种实现永久绑定,让二者独立扩展。原选项“固定判定关系”措辞不当,应按固定绑定关系理解。B、C、D分别对应组合、适配器、装饰模式。

题目 132

来源:知识点练习「面向对象技术」第 132 题(原站入口)。

某公司开发绘图软件,要求不同绘图程序能够绘制不同图形,且新的图形和绘图程序都可持续增加。题干以绘制直线和图形为例给出下图。第129空选择将抽象与实现分离、使二者独立变化的模式;第130空选择定义实现类接口的类;第131空选择适用情况;第132空判断模式类别。

图形与绘图程序的类图

本题回答第132空:该模式属于什么类别?

  • A. 创建型对象

  • B. 结构型对象

  • C. 行为型对象

  • D. 结构型类

答案与解析

平台答案:B。

整理解析

选B。桥接用对象组合把抽象部分与实现部分连接起来,属于结构型对象模式;两侧虽然也有继承层次,但模式的关键协作是对象间组合。

题目 133

来源:知识点练习「面向对象技术」第 133 题(原站入口)。

在C++、Java等面向对象语言中,哪个关键字可用来区分同名的对象属性与局部变量?

  • A. private

  • B. protected

  • C. public

  • D. this

答案与解析

平台答案:D。

整理解析

选D。Java可写this.x,C++可写this->x,明确访问当前对象的成员。其余选项是访问控制关键字。平台称protected允许父类访问子类成员不准确;Java还涉及同包访问,C++也有自身限制,不能用那一句话统一概括。

题目 134

来源:知识点练习「面向对象技术」第 134 题(原站入口)。

用面向对象方法开发系统时,下列与新冠病毒相关的哪组对象具有“一般—特殊”关系?

  • A. 确诊病人和治愈病人

  • B. 确诊病人和疑似病人

  • C. 医生和病人

  • D. 发热病人和确诊病人

答案与解析

平台答案:A。

整理解析

平台选A,将治愈病人看作曾确诊病人的特殊子集。但确诊、治愈也可建模为同一患者随时间改变的状态;若“确诊病人”仅指当前仍患病者,两者并非子类关系。题干未明确时间口径,平台结论依赖其采用的分类约定,不能仅凭状态变化推导继承。

题目 135

来源:知识点练习「面向对象技术」第 135 题(原站入口)。

某设计原则要求把针对同一类性质变化的类放在同一个包中;题干表述为:变化一旦影响该包,就影响其中所有类,而不影响其他包。这对应哪项原则?

  • A. 共同重用

  • B. 开放-封闭

  • C. 接口分离

  • D. 共同封闭

答案与解析

平台答案:D。

整理解析

选D,即共同封闭原则,强调把因同类原因一起变化的类组织在一起,让变化尽量局限于少量组件。题干和平台所说“一次变化必影响包中所有类、绝不影响其他包”过于绝对,这是模块组织目标,不是每次修改必须满足的结果。

题目 137

来源:知识点练习「面向对象技术」第 137 题(原站入口)。

UML对象图表示(137);从第138题的对象图中,选出与下列类图不一致的一项(138)。

题目配图

本题作答第137空。

  • A. 一组对象、接口、协作和它们之间的关系

  • B. 一组用例、参与者以及它们之间的关系

  • C. 某一时刻一组对象以及它们之间的关系

  • D. 以时间顺序组织的对象之间的交互活动

答案与解析

平台答案:C。

整理解析

对象图记录某一时刻的对象实例及实例间的连接,选C。平台把类图表述为“一组对象”不准确:类图描述类等类型及其关系,对象图才呈现实例快照。

题目 138

来源:知识点练习「面向对象技术」第 138 题(原站入口)。

UML对象图表示(137);从第138题的对象图中,选出与下列类图不一致的一项(138)。

题目配图

本题作答第138空。

  • A. 题目配图

  • B. 题目配图

  • C. 题目配图

  • D. 题目配图

答案与解析

平台答案:D。

整理解析

A端多重性为1、B端为*:每个B只能连接一个A,每个A可连接零个或多个B。D让同一个B连接两个A,违反A端的1,故选D;其余三图均符合。

题目 139

来源:知识点练习「面向对象技术」第 139 题(原站入口)。

儿童套餐由主餐(各类比萨)、饮料和玩具组成;各套餐品种可不同,制作流程相同,由前台服务员Waiter调度厨师。软件设计如下图。模式(139)将复杂对象的构建过程与表示分开,使同一流程能产生不同表示;(140)负责使用Builder接口组织对象构造。该模式归为(141),适用情形为(142)。

题目配图

本题作答第139空。

  • A. 生成器(Builder)

  • B. 抽象工厂(Abstract Factory)

  • C. 原型(Prototype)

  • D. 工厂方法(Factory Method)

答案与解析

平台答案:A。

整理解析

共同的制作步骤由指挥者组织,不同建造者决定各部件的具体表示,符合生成器(Builder)模式,选A。抽象工厂侧重成套产品,原型侧重复制实例,工厂方法把创建决定交给子类。

题目 140

来源:知识点练习「面向对象技术」第 140 题(原站入口)。

儿童套餐由主餐(各类比萨)、饮料和玩具组成;各套餐品种可不同,制作流程相同,由前台服务员Waiter调度厨师。软件设计如下图。模式(139)将复杂对象的构建过程与表示分开,使同一流程能产生不同表示;(140)负责使用Builder接口组织对象构造。该模式归为(141),适用情形为(142)。

题目配图

本题作答第140空。

  • A. PizzaBuilder

  • B. SpicyPizzaBuilder

  • C. Waiter

  • D. Pizza

答案与解析

平台答案:C。

整理解析

Waiter充当Director,通过PizzaBuilder接口按顺序调用构建步骤,选C;SpicyPizzaBuilder负责具体构建,Pizza是产品。原题“构造一个使用Builder接口的对象”应理解为借助该接口构造产品;平台把Product又称作具体产品建造者不准确,产品与建造者是不同角色。

题目 141

来源:知识点练习「面向对象技术」第 141 题(原站入口)。

儿童套餐由主餐(各类比萨)、饮料和玩具组成;各套餐品种可不同,制作流程相同,由前台服务员Waiter调度厨师。软件设计如下图。模式(139)将复杂对象的构建过程与表示分开,使同一流程能产生不同表示;(140)负责使用Builder接口组织对象构造。该模式归为(141),适用情形为(142)。

题目配图

本题作答第141空。

  • A. 创建型对象

  • B. 结构型对象

  • C. 行为型对象

  • D. 结构型类

答案与解析

平台答案:A。

整理解析

Builder解决复杂对象的创建,并通过指挥者与建造者对象协作完成,因此属于创建型对象模式,选A。

题目 142

来源:知识点练习「面向对象技术」第 142 题(原站入口)。

儿童套餐由主餐(各类比萨)、饮料和玩具组成;各套餐品种可不同,制作流程相同,由前台服务员Waiter调度厨师。软件设计如下图。模式(139)将复杂对象的构建过程与表示分开,使同一流程能产生不同表示;(140)负责使用Builder接口组织对象构造。该模式归为(141),适用情形为(142)。

题目配图

本题作答第142空。

  • A. 当一个系统应该独 立于它的产品创建、构成和表示时

  • B. 当一个类希望由它的子类来指定它所创建的对象的时候

  • C. 当要强调一系列相关的产品对象的设计以便进行联合使用时

  • D. 当构造过程必须允许被构造的对象有不同的表示时

答案与解析

平台答案:D。

整理解析

相同构造过程允许不同产品表示,正是Builder的针对性用途,选D。B对应工厂方法,C对应抽象工厂。A是创建型模式的广义独立性诉求,不能像平台解析那样仅凭这句话唯一判为原型模式。

题目 143

来源:知识点练习「面向对象技术」第 143 题(原站入口)。

依据下列UML类图,哪一项说法错误?( )

题目配图

  • A. 一个A1的对象可能与一个A2的对象关联

  • B. 一个A的非直接对象可能与一个A1 的对象关联

  • C. 类B1的对象可能通过A2与C1的对象关联

  • D. 有可能A的直接对象与B1的对象关联

答案与解析

平台答案:D。

整理解析

A标注{abstract},不能直接实例化,故D所说的A的直接对象不存在,选D。A1、A2实例可参与继承自A的关联,B1也可经A2间接关联C1。图中A端为2..4,表示一个B1关联2至4个A的实例;平台写成“2到多个”遗漏了上界4。

题目 144

来源:知识点练习「面向对象技术」第 144 题(原站入口)。

Java除自动垃圾回收外,还符合哪组特征?( )

①采用即时编译;②采用静态优化编译;③对象在堆空间分配;④对象在栈空间分配。

  • A. ①③

  • B. ①④

  • C. ②③

  • D. ②④

答案与解析

平台答案:A。

整理解析

按本题采用的典型JVM模型,JIT在运行时把字节码编译为机器码,对象在堆中分配,选①③,即A。纠正平台表述:即时编译不等于逐条解释执行,“Java程序最初都解释执行”也不是语言规定;栈存放栈帧、局部变量等,不能说方法代码存于栈中。AOT、逃逸分析等实现优化不改变本题的考查口径。

题目 145

来源:知识点练习「面向对象技术」第 145 题(原站入口)。

面向对象分析通常按哪一顺序开展活动?( )

  • A. 认定对象、组织对象、描述对象的相互作用、确定对象的操作

  • B. 认定对象、定义属性、组织对象、确定对象的操作

  • C. 认定对象、描述对象间的相互作用、确定对象的操作、识别包

  • D. 识别类及对象、识别关系、定义属性、确定对象的操作

答案与解析

平台答案:A。

整理解析

本题采用的分析流程为:认定对象→组织对象→描述对象间相互作用→确定对象操作,之后再定义内部信息,选A。纠正平台例子:门、窗是房屋的组成部分,不是房屋的子类;整体—部分关系不能当作继承关系。

题目 146

来源:知识点练习「面向对象技术」第 146 题(原站入口)。

面向对象设计要求客户不依赖自己不用的方法;原题又将其表述为“依赖抽象而非具体,抽象层不依赖细节”。它要求选择哪项原则?( )

  • A. 单一责任

  • B. 开放-封闭

  • C. 接口分离

  • D. 里氏替换

答案与解析

平台答案:C。

整理解析

首句“不强迫客户依赖不用的方法”指接口分离原则,平台答案C保留。但题干后半句“依赖抽象、抽象不依赖细节”属于依赖倒置原则,两者并不等价;平台把两项原则混写,不能据此记忆。

题目 147

来源:知识点练习「面向对象技术」第 147 题(原站入口)。

Bird和Cat继承Animal,Parrot继承Bird;bird、cat、parrot分别是Bird、Cat、Parrot的对象。第(147)空选择错误说法。另在Animal中定义move()接口,Bird、Cat、Parrot各自实现move();不同对象收到同一调用消息却给出不同结果,这种现象是(148)。

本题作答第147空。

  • A. cat和bird可看作是Animal的对象

  • B. parrot和bird可看作是Animal的对象

  • C. bird可以看作是Parrot的对象

  • D. parrot可以看作是Bird的对象

答案与解析

平台答案:C。

整理解析

子类实例可以按父类类型使用,所以cat、bird、parrot均可视作Animal,parrot也可视作Bird;Bird实例不因此成为Parrot实例,C错误。

题目 148

来源:知识点练习「面向对象技术」第 148 题(原站入口)。

Bird和Cat继承Animal,Parrot继承Bird;bird、cat、parrot分别是Bird、Cat、Parrot的对象。第(147)空选择错误说法。另在Animal中定义move()接口,Bird、Cat、Parrot各自实现move();不同对象收到同一调用消息却给出不同结果,这种现象是(148)。

本题作答第148空。

  • A. 封装

  • B. 继承

  • C. 消息传递

  • D. 多态

答案与解析

平台答案:D。

整理解析

同一move()调用因接收对象的实际类型而执行不同实现,体现多态,选D。继承建立类型层次,封装隐藏实现,消息传递描述对象间的请求机制。平台把消息一概称为异步通信不准确,面向对象消息也可以是同步调用。

题目 149

来源:知识点练习「面向对象技术」第 149 题(原站入口)。

用UML状态图描述系统、类或用例的动态行为时,通常建模的对象是(149)。图中当前活动状态为A;发生b=0事件且a>5为true时,经过(150)后D成为活动状态。第(151)空选择关于状态图的错误说法。

题目配图

本题作答第149空。

  • A. 系统的词汇

  • B. 反应型对象

  • C. 活动流程

  • D. 对象快照

答案与解析

平台答案:B。

整理解析

状态机描述对象如何响应事件、满足守卫条件并改变状态,适合反应型对象,选B。词汇属于静态结构建模,活动流程对应活动图,对象快照对应对象图。

题目 150

来源:知识点练习「面向对象技术」第 150 题(原站入口)。

用UML状态图描述系统、类或用例的动态行为时,通常建模的对象是(149)。图中当前活动状态为A;发生b=0事件且a>5为true时,经过(150)后D成为活动状态。第(151)空选择关于状态图的错误说法。

题目配图

本题作答第150空。

  • A. 一旦状态A的exit动作完成,或如果当前执行do动作,则终止执行

  • B. 一旦状态A和B的所有动作完成

  • C. 一旦正在进行的状态A完成

  • D. 一旦状态B的exit动作完成

答案与解析

平台答案:A。

整理解析

平台答案A。按图,C到D的迁移由when b=0触发、以a>5为守卫;从当前子状态A离开时终止尚在执行的do活动,执行A的exit动作及必要的外围退出步骤,然后进入D,不必先经过B或等C自然完成。A的文字不严谨:终止do与执行exit不是二选一。平台把图中的b=0写成b=5,并声称须等C完成,均应纠正。

题目 151

来源:知识点练习「面向对象技术」第 151 题(原站入口)。

用UML状态图描述系统、类或用例的动态行为时,通常建模的对象是(149)。图中当前活动状态为A;发生b=0事件且a>5为true时,经过(150)后D成为活动状态。第(151)空选择关于状态图的错误说法。

题目配图

本题作答第151空。

  • A. 动作可以在状态内执行,也可以在状态转换时执行

  • B. 当触发转换的事件发生并且转换没有指定的监护条件时,对象将离开当前状态,并且其do动作终止

  • C. when(…)称为时间事件

  • D. 状态由事件触发

答案与解析

平台答案:D。

整理解析

平台答案D保留:严格说事件触发的是迁移,对象随后进入目标状态。但C同样错误,when(条件)是变化事件;时间事件通常用after(时长)或at(时刻)表示。因此本题不能视为只有一个无歧义错误选项。B还隐含外部迁移且没有其他冲突的前提;内部迁移不会退出状态。

题目 152

来源:知识点练习「面向对象技术」第 152 题(原站入口)。

股票代理Broker按照客户的买卖等操作指示处理股票,设计如下图。模式(152)把请求封装为对象,使客户可按请求参数化,并支持请求排队、日志和可撤销操作;(153)声明执行操作的接口。该模式属于(154),适用情形为(155)。

题目配图

本题作答第152空。

  • A. 命令(Command)

  • B. 观察者(Observer)

  • C. 状态(State)

  • D. 中介者(Mediator)

答案与解析

平台答案:A。

整理解析

将操作请求对象化的是命令模式,选A。Broker持有并调用命令,具体命令把execute()委托给Stock的相应操作。排队、日志和撤销可以在此结构上扩展;图中execute()本身并不自动实现撤销。

题目 153

来源:知识点练习「面向对象技术」第 153 题(原站入口)。

股票代理Broker按照客户的买卖等操作指示处理股票,设计如下图。模式(152)把请求封装为对象,使客户可按请求参数化,并支持请求排队、日志和可撤销操作;(153)声明执行操作的接口。该模式属于(154),适用情形为(155)。

题目配图

本题作答第153空。

  • A. Operation

  • B. sellOperation/BayOperation/ViewOperation

  • C. Broker

  • D. Stock

答案与解析

平台答案:A。

整理解析

Operation位于命令层次的上层,声明execute()接口,选A;SellOperation、BuyOperation、ViewOperation为具体命令,Broker为调用者,Stock为接收者。原选项B保留了sellOperation/BayOperation的拼写,题图对应SellOperation/BuyOperation。

题目 154

来源:知识点练习「面向对象技术」第 154 题(原站入口)。

股票代理Broker按照客户的买卖等操作指示处理股票,设计如下图。模式(152)把请求封装为对象,使客户可按请求参数化,并支持请求排队、日志和可撤销操作;(153)声明执行操作的接口。该模式属于(154),适用情形为(155)。

题目配图

本题作答第154空。

  • A. 结构类型

  • B. 结构型对象

  • C. 创建类型

  • D. 行为型对象

答案与解析

平台答案:D。

整理解析

命令模式通过命令对象分离请求者与执行者,组织对象间的职责和调用,属于行为型对象模式,选D。

题目 155

来源:知识点练习「面向对象技术」第 155 题(原站入口)。

股票代理Broker按照客户的买卖等操作指示处理股票,设计如下图。模式(152)把请求封装为对象,使客户可按请求参数化,并支持请求排队、日志和可撤销操作;(153)声明执行操作的接口。该模式属于(154),适用情形为(155)。

题目配图

本题作答第155空。

  • A. 一个对象必须通知其他对象,而它又不能假定其他对象是谁

  • B. 抽象出待执行的动作以参数化某对象

  • C. 一个对象的行为决定于其状态且必须在运行时刻根据状态改变行为

  • D. 一个对象引用其他对象并且直接与这些对象通信而导致难以复用该对象

答案与解析

平台答案:B。

整理解析

把待执行动作封装为命令对象,再用它配置调用者,符合B。A是不预知具体观察者的通知场景,C对应状态模式,D对应以中介者减少直接通信耦合。

题目 156

来源:知识点练习「面向对象技术」第 156 题(原站入口)。

面向对象设计阶段主要包括哪些活动?( )

  • A. 认定对象、组织对象、描述对象间的相互作用、确定对象的操作

  • B. 认定对象、定义属性、组织对象、确定对象的操作

  • C. 识别类及对象、确定对象的操作、描述对象间的相互作用、识别关系

  • D. 识别类及对象、定义属性、定义服务、识别关系、识别包

答案与解析

平台答案:D。

整理解析

本题教材口径下,设计包括识别类及对象、定义属性与服务、识别关系和包,选D;A列出的是相应的分析活动。实际开发中分析与设计会迭代,活动名称并非完全互斥。

题目 157

来源:知识点练习「面向对象技术」第 157 题(原站入口)。

某包中的类应共同重用:一旦重用其中一个类,就需要重用包内其余类。该说法对应哪项设计原则?( )

  • A. 接口分离

  • B. 开放-封闭

  • C. 共同封闭

  • D. 共同重用

答案与解析

平台答案:D。

整理解析

题目对应共同重用原则,选D:应把会被一起重用的类组织在同一包,避免使用者被迫依赖无关类。“重用一个就必须实际使用全部类”是教材的简化表述;共同封闭关注相同变更原因,不意味着每次修改都影响包内所有类而绝不影响其他包。

题目 158

来源:知识点练习「面向对象技术」第 158 题(原站入口)。

某电商系统按面向对象方法识别出网店、商品、购物车、订单买家、库存,以及支付(微信、支付宝)等类。购物车与商品适合采用(158)关系,网店与商品适合采用(159)关系。

本题作答第158空。

  • A. 关联

  • B. 依赖

  • C. 组合

  • D. 聚合

答案与解析

平台答案:D。

整理解析

平台按购物车为整体、商品可脱离购物车独立存在的建模假设选D(聚合)。这不是仅凭类名就能唯一确定的关系;若购物车只引用商品目录中的商品,也可建普通关联,并让购物车与购物项建立组合。保留题目的聚合口径。

题目 159

来源:知识点练习「面向对象技术」第 159 题(原站入口)。

某电商系统按面向对象方法识别出网店、商品、购物车、订单买家、库存,以及支付(微信、支付宝)等类。购物车与商品适合采用(158)关系,网店与商品适合采用(159)关系。

本题作答第159空。

  • A. 依赖

  • B. 关联

  • C. 组合

  • D. 聚合

答案与解析

平台答案:C。

整理解析

平台答案C,隐含商品是网店独占拥有、随店删除的商品记录。题干没有说明独占所有权或生命周期,因此仅由“网店包含商品”不能推出组合;若商品可跨店共享或在店关闭后保留,关联或聚合也可能合理。组合强调排他的整体—部分所有权,不能只机械地等同于出生、消亡时刻完全一致。

题目 160

来源:知识点练习「面向对象技术」第 160 题(原站入口)。

系统要求登录失败次数不超过3次,登录状态图如下。当前活动状态为Logging in,发生Valid Entry时的结果是(160);图中[tries < 3]与tries++分别表示(161)和(162)。

题目配图

本题作答第160空。

  • A. 保持在Logging in状态

  • B. 若[tries < 3]为true,则Logged in变为下一个活动状态

  • C. Logged in立刻变为下一 个活动状态

  • D. 若tries=3为true,则Logging Denied变为下一个活动状态

答案与解析

平台答案:B。

整理解析

Valid Entry标注在通向Logged in的边上,只有守卫tries<3为真才迁移,故平台答案B;不能说该事件在tries=3时必然触发另一条边。题图另有实质缺陷:Invalid Entry画成外部自转换,会在tries++后重新进入Logging in并执行entry/tries=0,使失败计数无法累积到3。初始化应移到仅首次进入的路径,或调整为不重置计数的内部处理。

题目 161

来源:知识点练习「面向对象技术」第 161 题(原站入口)。

系统要求登录失败次数不超过3次,登录状态图如下。当前活动状态为Logging in,发生Valid Entry时的结果是(160);图中[tries < 3]与tries++分别表示(161)和(162)。

题目配图

本题作答第161空。

  • A. 状态

  • B. 转换

  • C. 监护条件

  • D. 转换后效果

答案与解析

平台答案:C。

整理解析

方括号中的tries<3是守卫(监护)条件,决定该迁移是否允许发生,选C。图中Invalid Entry的外部自转换会再次执行Logging in的entry/tries=0,导致失败计数被清零;这项图示缺陷不改变本空对方括号的识别。

题目 162

来源:知识点练习「面向对象技术」第 162 题(原站入口)。

系统要求登录失败次数不超过3次,登录状态图如下。当前活动状态为Logging in,发生Valid Entry时的结果是(160);图中[tries < 3]与tries++分别表示(161)和(162)。

题目配图

本题作答第162空。

  • A. 状态

  • B. 转换

  • C. 转换后效果

  • D. 监护条件

答案与解析

平台答案:C。

整理解析

斜线后的tries++是迁移执行时的效果,按选项术语选C“转换后效果”;它不是整个状态转换,也不表示必须在进入目标状态之后才执行。图中外部自转换随后又执行entry/tries=0,抵消计数累积,故原图不足以正确实现三次失败限制。

题目 163

来源:知识点练习「面向对象技术」第 163 题(原站入口)。

系统中各组Group具有不同数据访问权限;每个User属于一个或多个组,每组包含零个或多个用户。用户与组的映射交给独立对象维护,设计如下图。模式(163)用一个对象封装对象间交互,免去用户与组的显式相互引用,降低耦合并允许独立改变交互。它属于(164),适用情形为(165)。

题目配图

本题作答第163空。

  • A. 状态(State)

  • B. 策略(Strategy)

  • C. 解释器(Interpreter)

  • D. 中介者(Mediator)

答案与解析

平台答案:D。

整理解析

UserGroupMapper集中维护用户与组的交互,双方经它协作而非直接互相引用,符合中介者模式,选D。关键是集中协调交互;单纯增加数据库映射表并不自动构成中介者模式。

题目 164

来源:知识点练习「面向对象技术」第 164 题(原站入口)。

系统中各组Group具有不同数据访问权限;每个User属于一个或多个组,每组包含零个或多个用户。用户与组的映射交给独立对象维护,设计如下图。模式(163)用一个对象封装对象间交互,免去用户与组的显式相互引用,降低耦合并允许独立改变交互。它属于(164),适用情形为(165)。

题目配图

本题作答第164空。

  • A. 创建型类

  • B. 创建型对象

  • C. 行为型对象

  • D. 行为型类

答案与解析

平台答案:C。

整理解析

中介者通过对象协作分配和集中协调交互职责,属于行为型对象模式,选C。

题目 165

来源:知识点练习「面向对象技术」第 165 题(原站入口)。

系统中各组Group具有不同数据访问权限;每个User属于一个或多个组,每组包含零个或多个用户。用户与组的映射交给独立对象维护,设计如下图。模式(163)用一个对象封装对象间交互,免去用户与组的显式相互引用,降低耦合并允许独立改变交互。它属于(164),适用情形为(165)。

题目配图

本题作答第165空。

  • A. 需要使用一个算法的不同变体

  • B. 有一个语言需要解释执行,并且可将句子表示为一个抽象语法树

  • C. 一个对象的行为决定于其状态且必须在运行时刻根据状态改变行为

  • D. 一个对象引用其他对象并且直接与这些对象通信而导致难以复用该对象

答案与解析

平台答案:D。

整理解析

当对象因直接引用、通信而与许多伙伴紧密耦合时,可把交互交给中介者,选D。A对应策略,B对应解释器,C对应状态模式。

题目 166

来源:知识点练习「面向对象技术」第 166 题(原站入口)。

购物中心收银软件需在不同时期切换打折、返利、满减等促销活动,适合采用什么模式?( )

  • A. 策略(Strategy)

  • B. 访问者(Visitor)

  • C. 观察者(Observer)

  • D. 中介者(Mediator)

答案与解析

平台答案:A。

整理解析

把各促销计算规则分别封装为可替换算法,由收银流程选用,属于策略模式,选A。访问者侧重为对象结构增加操作,观察者侧重通知,中介者侧重协调对象间交互。

题目 167

来源:知识点练习「面向对象技术」第 167 题(原站入口)。

哪种机制在程序运行时把一次调用与实际响应它的代码结合起来?( )

  • A. 强类型

  • B. 弱类型

  • C. 静态绑定

  • D. 动态绑定

答案与解析

平台答案:D。

整理解析

运行时确定此次调用应执行的实现是动态绑定,选D;静态绑定在运行前确定调用目标。强类型、弱类型讨论类型约束,不是调用绑定时机。

题目 168

来源:知识点练习「面向对象技术」第 168 题(原站入口)。

面向对象设计要求包依赖图不存在环,这对应哪项原则?( )

  • A. 单一责任

  • B. 无环依赖

  • C. 依赖倒置

  • D. 里氏替换

答案与解析

平台答案:B。

整理解析

无环依赖原则要求包之间的有向依赖不形成回路,选B,使依赖结构可分层、包可较独立地发布和测试。“有向无环图”是准确名称,平台所写“直接的无环图形”不规范。

题目 169

来源:知识点练习「面向对象技术」第 169 题(原站入口)。

面向对象分析首先进行(169);面向对象程序设计语言用于支持面向对象(170)。

本题作答第169空。

  • A. 组织对象

  • B. 描述对象间的相互作用

  • C. 认定对象

  • D. 确定对象的操作

答案与解析

平台答案:C。

整理解析

首先从问题领域识别需要建模的对象,即认定对象,选C;之后再组织对象、分析交互和确定操作。

题目 170

来源:知识点练习「面向对象技术」第 170 题(原站入口)。

面向对象分析首先进行(169);面向对象程序设计语言用于支持面向对象(170)。

本题作答第170空。

  • A. 用例设计

  • B. 分析

  • C. 需求分析

  • D. 实现

答案与解析

平台答案:D。

整理解析

面向对象程序设计语言把分析、设计得到的类和协作落实为程序,用于面向对象实现,选D。

题目 171

来源:知识点练习「面向对象技术」第 171 题(原站入口)。

游戏中有野鸭、红头鸭等多种鸭子,它们都会游泳、呱呱叫,颜色随种类不同。鸭子父类实现叫声与游泳方法,把显示颜色声明为抽象方法,由野鸭、红头鸭分别实现,此机制为(171)。向这些不同类型的对象发送同一显示颜色消息,各自显示本类颜色,这一现象为(172)。

本题作答第171空。

  • A. 继承

  • B. 聚合

  • C. 组合

  • D. 多态

答案与解析

平台答案:A。

整理解析

子类继承鸭子父类的共同实现,并实现父类声明的抽象方法,本空考查继承,选A。平台把聚合、组合解释为“由多个子类对象组成”不准确:它们描述整体与部分,不要求两端存在父子类关系。

题目 172

来源:知识点练习「面向对象技术」第 172 题(原站入口)。

游戏中有野鸭、红头鸭等多种鸭子,它们都会游泳、呱呱叫,颜色随种类不同。鸭子父类实现叫声与游泳方法,把显示颜色声明为抽象方法,由野鸭、红头鸭分别实现,此机制为(171)。向这些不同类型的对象发送同一显示颜色消息,各自显示本类颜色,这一现象为(172)。

本题作答第172空。

  • A. 覆盖

  • B. 重载

  • C. 动态绑定

  • D. 多态

答案与解析

平台答案:D。

整理解析

同一消息交给不同类型的对象会执行各自实现,体现多态,选D。覆盖是子类重新实现父类方法,动态绑定是运行时选择实现的机制,重载则要求同名方法具有可区分的参数签名。平台末句“A、D”是在汇总两小问,Q171选A、Q172选D,不能把本题当作多选。

题目 173

来源:知识点练习「面向对象技术」第 173 题(原站入口)。

面向对象分析认定对象时,通常先把应用领域自然存在的哪类语言成分作为候选对象?( )

  • A. 问题

  • B. 关系

  • C. 名词

  • D. 动词

答案与解析

平台答案:C。

整理解析

领域叙述中的名词常指向实体,可用来发现候选对象,选C。仍需按系统职责筛选,不能把每个名词都直接建成类;动词通常更有助于发现操作。

题目 174

来源:知识点练习「面向对象技术」第 174 题(原站入口)。

一个类只承担一种职责,修改它的原因应只有一个,这体现什么原则?( )

  • A. 单一责任

  • B. 开放-封闭

  • C. 接口分离

  • D. 依赖倒置

答案与解析

平台答案:A。

整理解析

这是单一责任原则,选A。“一个修改原因”强调同一职责或同一类业务主体的变化,不等于类只能有一个方法。开闭原则关注扩展方式,接口分离关注客户所需接口,依赖倒置关注抽象依赖。

题目 175

来源:知识点练习「面向对象技术」第 175 题(原站入口)。

UML活动图主要用于描述(175)。在下图中,A1执行结束后,可能的活动执行序列是(176)。

题目配图

本题作答第175空。

  • A. 系统在它的周边环境的语境中所提供的外部可见服务

  • B. 某一时刻一组对象以及它们之间的关系

  • C. 系统内从一个活动到另一个活动的流程

  • D. 对象的生命周期中某个条件或者状态

答案与解析

平台答案:C。

整理解析

活动图描述活动之间的控制流或对象流,选C。A指向用例所提供的外部服务,B是对象快照,D是状态。

题目 176

来源:知识点练习「面向对象技术」第 176 题(原站入口)。

UML活动图主要用于描述(175)。在下图中,A1执行结束后,可能的活动执行序列是(176)。

题目配图

本题作答第176空。

  • A. A2、A3、A4和A5

  • B. A3、A4和A5,或A2、A4和A5

  • C. A2、A4和A5

  • D. A2或A3、A4和A5

答案与解析

平台答案:D。

整理解析

菱形分支使A1之后选择A2,或选择A3后再分叉执行A4、A5,故D应读作“A2,或(A3、A4和A5)”。A4与A5可并发,图未规定二者先后次序;后面的汇合条需等待两者完成。

题目 177

来源:知识点练习「面向对象技术」第 177 题(原站入口)。

UML构件图表示构件的组织与依赖,通常包含构件、接口和各类关系,主要体现系统的静态( )视图。

  • A. 关联

  • B. 实现

  • C. 结构

  • D. 行为

答案与解析

平台答案:B。

整理解析

按UML视图分类,构件图侧重软件构件及接口的静态实现视图,选B。构件图本身属于结构图,但本题问的是视图名称;物理节点及构件部署位置应主要由部署图描述。

题目 178

来源:知识点练习「面向对象技术」第 178 题(原站入口)。

系统按日志级别采用不同记录方式。各日志处理对象检查消息级别,达到自身级别就记录,否则跳过;之后都把消息交给下一个处理对象。类图如下。模式(178)把处理对象前后连接,使多个对象有机会处理同一请求,降低发送者与具体接收者的耦合;它属于(179),适用情形为(180)。

题目配图

本题作答第178空。

  • A. 责任链(Chain of Responsibility)

  • B. 策略(Strategy)

  • C. 过滤器(Filter)

  • D. 备忘录(Memento)

答案与解析

平台答案:A。

整理解析

Logger通过nextLogger连接后继,各节点自行判断是否处理,构成责任链,选A。本题明确记录后仍继续传递,因此允许多个节点处理;不能额外假定第一个节点处理后必定停止。

题目 179

来源:知识点练习「面向对象技术」第 179 题(原站入口)。

系统按日志级别采用不同记录方式。各日志处理对象检查消息级别,达到自身级别就记录,否则跳过;之后都把消息交给下一个处理对象。类图如下。模式(178)把处理对象前后连接,使多个对象有机会处理同一请求,降低发送者与具体接收者的耦合;它属于(179),适用情形为(180)。

题目配图

本题作答第179空。

  • A. 行为型类

  • B. 行为型对象

  • C. 结构型类

  • D. 结构型对象

答案与解析

平台答案:B。

整理解析

责任链通过处理对象及其后继引用分配请求处理职责,属于行为型对象模式,选B。

题目 180

来源:知识点练习「面向对象技术」第 180 题(原站入口)。

系统按日志级别采用不同记录方式。各日志处理对象检查消息级别,达到自身级别就记录,否则跳过;之后都把消息交给下一个处理对象。类图如下。模式(178)把处理对象前后连接,使多个对象有机会处理同一请求,降低发送者与具体接收者的耦合;它属于(179),适用情形为(180)。

题目配图

本题作答第180空。

  • A. 不同的标准过滤一组对象,并通过逻辑操作以解耦的方式将它们链接起来

  • B. 可处理一个请求的对象集合应被动态指定

  • C. 必须保存一个对象在某一个时刻的状态,需要时它才能恢复到先前的状态

  • D. 一个类定义了多种行为,并且以多个条件语句的形式出现

答案与解析

平台答案:B。

整理解析

通过调整链中的对象及先后顺序,可动态指定参与处理请求的对象集合,选B。A描述过滤,C描述保存和恢复状态的备忘录,D是可以用策略分离多种行为的典型情形。

题目 181

来源:知识点练习「面向对象技术」第 181 题(原站入口)。

新能源汽车中,电能汽车与光能汽车采用不同的发动机驱动方法。客户端希望统一调用驱动接口,以屏蔽这些方法的差异,应采用哪种模式?( )

  • A. 中介者(Mediator)

  • B. 访问者(Visitor)

  • C. 观察者(Observer)

  • D. 适配器(Adapter)

答案与解析

平台答案:D。

整理解析

适配器向客户端提供统一目标接口,并把调用转换为各已有驱动接口的操作,选D。关键是接口转换;中介者协调交互,观察者负责通知,访问者为对象结构定义外部操作。

历年真题:2026年5月(考生回忆版)

本节收录本卷归入本模块的 14 题;题号沿用试卷编号;同材料的不同小问分别保留。

2026-05 Q010

来源:2026年5月软件设计师综合知识真题(考生回忆版)第 10 题(原站试卷目录)。

智能家居有四项设计要求。①中央控制器只能有一个实例;②飞利浦、小米等品牌的灯具接口不同,但系统须通过统一接口控制,并能在不修改已有系统代码的情况下接入新接口不兼容的灯具;③温度变化时,空调、加湿器、窗帘等多个设备都要响应;④调光、开机、放幕布等操作被封装为实现统一接口的动作类,按钮持有动作对象并在点击时触发,不需了解设备内部细节。为各项要求选择合适的模式。

本题回答第10题,即上述第1项要求。

  • A. 工厂方法(Factory Method)

  • B. 单例(Singleton)

  • C. 抽象工厂(Abstract Factory)

  • D. 生成器(Builder)

答案与解析

平台答案:B。

整理解析

限制中央控制器只能有一个实例,对应单例模式B。其关键是控制实例数量,而不是按产品族创建对象或分步骤装配对象。

2026-05 Q011

来源:2026年5月软件设计师综合知识真题(考生回忆版)第 11 题(原站试卷目录)。

智能家居有四项设计要求。①中央控制器只能有一个实例;②飞利浦、小米等品牌的灯具接口不同,但系统须通过统一接口控制,并能在不修改已有系统代码的情况下接入新接口不兼容的灯具;③温度变化时,空调、加湿器、窗帘等多个设备都要响应;④调光、开机、放幕布等操作被封装为实现统一接口的动作类,按钮持有动作对象并在点击时触发,不需了解设备内部细节。为各项要求选择合适的模式。

本题回答第11题,即上述第2项要求。

  • A. 适配器(Adapter)

  • B. 代理(Proxy)

  • C. 外观(Facade)

  • D. 装饰器(Decorator)

答案与解析

平台答案:A。

整理解析

保留既有灯具接口,再用转换层对外提供系统需要的统一接口,就是适配器模式A。它解决的是接口不兼容,而不是增加访问控制或给对象叠加职责。

2026-05 Q012

来源:2026年5月软件设计师综合知识真题(考生回忆版)第 12 题(原站试卷目录)。

智能家居有四项设计要求。①中央控制器只能有一个实例;②飞利浦、小米等品牌的灯具接口不同,但系统须通过统一接口控制,并能在不修改已有系统代码的情况下接入新接口不兼容的灯具;③温度变化时,空调、加湿器、窗帘等多个设备都要响应;④调光、开机、放幕布等操作被封装为实现统一接口的动作类,按钮持有动作对象并在点击时触发,不需了解设备内部细节。为各项要求选择合适的模式。

本题回答第12题,即上述第3项要求。

  • A. 观察者(Observer)

  • B. 迭代器(Iterator)

  • C. 备忘录(Memento)

  • D. 策略(Strategy)

答案与解析

平台答案:A。

整理解析

一个温度源变化后通知多个订阅设备更新,符合一对多通知关系,选观察者A。

2026-05 Q013

来源:2026年5月软件设计师综合知识真题(考生回忆版)第 13 题(原站试卷目录)。

智能家居有四项设计要求。①中央控制器只能有一个实例;②飞利浦、小米等品牌的灯具接口不同,但系统须通过统一接口控制,并能在不修改已有系统代码的情况下接入新接口不兼容的灯具;③温度变化时,空调、加湿器、窗帘等多个设备都要响应;④调光、开机、放幕布等操作被封装为实现统一接口的动作类,按钮持有动作对象并在点击时触发,不需了解设备内部细节。为各项要求选择合适的模式。

本题回答第13题,即上述第4项要求。

  • A. 备忘录(Memento)

  • B. 命令(Command)

  • C. 状态模式(来源英文写作Stare)

  • D. 策略(Strategy)

答案与解析

平台答案:B。

整理解析

把一次设备操作封装成带统一执行接口的对象,按钮只负责调用这个对象,属于命令模式B。来源C项英文Stare不是状态模式的标准名称;标准名称为State,该拼写问题不改变本题选择。

2026-05 Q014

来源:2026年5月软件设计师综合知识真题(考生回忆版)第 14 题(原站试卷目录)。

这组题分别要求判断类与对象的关系,并从汽车相关搭配中辨认该关系。本题回答第14题(第一空:关系描述)。

  • A. 类是对象的具体实例

  • B. 一个类至多只能产生一个对象

  • C. 类提供模板,对象是按该模板建立的实例

  • D. 对象属于抽象层面,而类是具体的

答案与解析

平台答案:C。

整理解析

类描述一组实例共同遵守的结构和行为,对象是据此产生的具体实例,因此C的方向正确。其余选项颠倒抽象与实例关系,或给一般类强加只能创建一个对象的限制。

2026-05 Q015

来源:2026年5月软件设计师综合知识真题(考生回忆版)第 15 题(原站试卷目录)。

这组题分别要求判断类与对象的关系,并从汽车相关搭配中辨认该关系。本题回答第15题(第二空:对应搭配)。

  • A. 汽车颜色与那辆白色比亚迪

  • B. 汽车与刹车功能

  • C. 汽车与汽车颜色

  • D. 汽车与那辆白色比亚迪

答案与解析

平台答案:D。

整理解析

“汽车”可作类,“那辆白色比亚迪”指一个确定实例,因此D成立;颜色是属性,刹车是行为,不能充当本题要求的实例。

2026-05 Q031

来源:2026年5月软件设计师综合知识真题(考生回忆版)第 31 题(原站试卷目录)。

猫类属于动物类的一种特殊类型,可以直接使用动物类已有的“呼吸”“睡觉”方法,无须重新定义。这体现哪项面向对象技术?

  • A. 实例化

  • B. 继承

  • C. 封装

  • D. 依赖

答案与解析

平台答案:B。

整理解析

猫类作为动物类的子类复用已有方法,体现继承,选B。题目没有描述创建某个猫对象,也没有主要讨论隐藏实现细节。

2026-05 Q045

来源:2026年5月软件设计师综合知识真题(考生回忆版)第 45 题(原站试卷目录)。

支付系统原先只支持支付宝,现要加入微信支付。只需增加支付实现类并完成配置,不必改动既有业务逻辑,这体现了( )原则。

  • A. 开放—封闭

  • B. 单一职责

  • C. 依赖倒置

  • D. 里氏替换

答案与解析

平台答案:A。

整理解析

选 A。通过新增实现扩展支付能力,同时保持原业务逻辑稳定,体现“对扩展开放、对修改关闭”。依赖抽象可以帮助实现这一目标,但题目直接描述的是开放—封闭原则。

2026-05 Q049

来源:2026年5月软件设计师综合知识真题(考生回忆版)第 49 题(原站试卷目录)。

面向对象中的封装主要为了( )。

  • A. 让代码跨平台运行

  • B. 提高执行速度

  • C. 隐藏对象内部细节,只公开必要接口

  • D. 允许任意修改代码

答案与解析

平台答案:C。

整理解析

选 C。封装把内部状态与实现细节放在受控边界内,外部通过规定接口使用对象,可减少对内部实现的依赖。

2026-05 Q058

来源:2026年5月软件设计师综合知识真题(考生回忆版)第 58 题(原站试卷目录)。

下图表示作者(Author)写书(Book)。关联两端的 1 和 * 对应的业务规则是( )。

题目配图

  • A. 一位作者可写零本或多本书

  • B. 一本书可由多位作者合作编写

  • C. 作者与书之间没有明确数量关系

  • D. 一位作者只能写一本书

答案与解析

平台答案:A。

整理解析

选 A。Book 端的 * 表示一位作者可关联零本或多本书;Author 端的 1 表示在该模型中每本书恰有一位作者。平台对 B 的解释把数量方向说反了,“一本书有多位作者”要求作者端允许多个,图中并非如此。

2026-05 Q066

来源:2026年5月软件设计师综合知识真题(考生回忆版)第 66 题(原站试卷目录)。

下列哪个场景体现运行时多态( )?

  • A. 把属性设为私有并封装

  • B. 子类覆盖父类方法,父类引用指向子类对象时调用子类实现

  • C. 同一个类中有多个同名、参数类型列表不同的方法

  • D. 一个类继承多个父类

答案与解析

平台答案:B。

整理解析

选 B。对可动态分派的方法,实际调用哪个覆盖实现由运行时对象决定。A 是封装,C 描述重载,D 描述多继承;方法隐藏或非虚方法的同名定义不自动产生这种动态分派。

2026-05 Q068

来源:2026年5月软件设计师综合知识真题(考生回忆版)第 68 题(原站试卷目录)。

下图中,房屋 House 与房间 Room 之间带实心菱形的连线表示( )。

题目配图

  • A. 实现:House 实现 Room 的接口

  • B. 聚合:拆除房屋后房间仍可独立存在

  • C. 组合:房屋与房间生命周期相同,屋毁房亡

  • D. 泛化:House 是 Room 的子类

答案与解析

平台答案:C。

整理解析

选 C。实心菱形在 House 端,表示 House 是组合关系中的整体,Room 是组成部分。组合强调独占的组成关系,整体销毁时仍属于它的部分随之销毁;平台所说“完全相同的生命周期”过于绝对,部分可以晚于整体创建,也可能先被移除。

2026-05 Q074

来源:2026年5月软件设计师综合知识真题(考生回忆版)第 74 题(原站试卷目录)。

按下列 UML 状态机图,依次处理事件 e2、e3、e1、e2、e3,最终 x 的值为( );所处状态为( )。

题目配图

请作答:第 74 题(第一空,x 的值)

  • A. 4

  • B. 3

  • C. 2

  • D. 9

答案与解析

平台答案:B。

整理解析

本问选 B。初始进入 A 后 x=2。第一个 e2 先判断 x<4 成立,再依次执行 A 的退出动作 x--、转换动作 x++、B 的进入动作 x++,到达 (B,3)。随后 e3 得到 (B,4),e1 得到 (B,2);下一个 e2 因 x>5 不成立而不转移,最后 e3 得到 (B,3)。B 内部的 e1、e3 不触发退出或重新进入。最终 x=3、状态 B,分别对应第 74 题 B、第 75 题 C。

2026-05 Q075

来源:2026年5月软件设计师综合知识真题(考生回忆版)第 75 题(原站试卷目录)。

按下列 UML 状态机图,依次处理事件 e2、e3、e1、e2、e3,最终 x 的值为( );所处状态为( )。

题目配图

请作答:第 75 题(第二空,所处状态)

  • A. A

  • B. 已结束

  • C. B

  • D. C

答案与解析

平台答案:C。

整理解析

本问选 C,状态为 B。与第 74 题共用状态图和事件序列:首次 e2 从 A 转入 B;在 B 中处理 e3、e1 后 x=2,下一次 e2 不满足 x>5,最后 e3 仅把 x 加到 3,状态仍为 B。平台没有为本小问单列解析,可参照第 74 题的完整推导。

2025年下半年软件设计师考试基础知识真题(考生回忆版)

本节已整理 3 条来源记录;题号沿用来源,答案与解析默认收起。

2025-11 Q006

来源:第 6 题(原站入口)。

下列哪项不属于面向对象设计的基本原则( )?

  • A.

    过程优先

  • B.

    单一职责

  • C.

    依赖倒置

  • D.

    开放-封闭

答案与解析

平台答案:A。

整理解析

选A。单一职责强调类的职责集中;依赖倒置强调依赖抽象;开放—封闭强调以扩展应对变化、减少修改既有实现。“过程优先”不是这些面向对象设计原则之一。

2025-11 Q015

来源:第 15 题(原站入口)。

在面向对象方法中,继承的主要作用是什么( )?

  • A.

    实现对象之间的消息传递

  • B.

    限制类的访问权限

  • C.

    使子类拥有父类的属性和方法

  • D.

    隐藏对象的实现细节

答案与解析

平台答案:C。

整理解析

选C。继承使子类在父类基础上复用并扩展属性和行为。A描述对象通信,B描述访问控制,D描述封装与信息隐藏;具体成员能否被子类直接访问仍受语言访问规则约束。

2025-11 Q030

来源:第 30 题(原站入口)。

采用面向对象方法开发系统时,如果两个类的关系较复杂,简单关联或继承不足以表达,通常引入新类描述该关系。下列哪一对需要为两者的关系创建新类( )?

  • A.

    员工和部门

  • B.

    图书馆和书籍

  • C.

    员工和项目

  • D.

    导师和学生

答案与解析

平台答案:C。

整理解析

平台答案为C。按常见业务建模,员工参与项目的关系可带有角色、参与时间、工时等信息,适合用“参与”关联类表示。但这些关系属性和多重性并未在题干中具体给出;仅凭实体名称,不能证明只有员工—项目必需创建新类。

补充与纠错

关联类用于表达联系自身的属性或行为,多对多关系也能用普通关联表达,并非一见多对多就必须增加类。原解析末句“排除ABC”与其选择C矛盾,按其行文应为“排除ABD”;即使改正该笔误,其排他结论仍须业务条件支持。本题按面向对象关联建模归入object-oriented。

2025年上半年软件设计师考试基础知识真题(考生回忆版)

本节已整理 2 条来源记录;题号沿用来源,答案与解析默认收起。

2025-05 Q015

来源:第 15 题(原站入口)。

气象监测系统的天气数据变化后,多种显示设备(如PC应用、手机应用)都需要及时更新。最适合这一需求的设计模式是( )。

  • A.

    观察者(Observer)

  • B.

    备忘录(Memento)

  • C.

    策略(Strategy)

  • D.

    状态(State)

答案与解析

平台答案:A。

整理解析

选A。天气数据作为被观察对象发生变化时,向依赖它的多个显示对象发出通知,使PC端、手机端分别更新,符合观察者的一对多依赖关系。备忘录用于保存与恢复状态,策略用于替换算法,状态模式处理对象内部状态与行为的对应。

补充与纠错

及时更新是观察者关系的业务目标,不代表模式本身提供实时性、可靠投递或强一致性的保证。

2025-05 Q029

来源:第 29 题(原站入口)。

用面向对象方法开发电商平台时,OrderService类既创建用户订单,又负责记录订单日志和发送确认邮件。按题意,它违反了( )原则。

  • A.

    里氏替换

  • B.

    单一职责

  • C.

    接口隔离

  • D.

    开放-封闭

答案与解析

平台答案:B。

整理解析

选B。若订单创建、日志实现、邮件发送这些会因不同原因变化的职责都由OrderService直接承担,就偏离单一职责原则。可把日志、通知等交给相应组件,让订单服务集中处理订单业务。

补充与纠错

单一职责关注变化原因,不是方法数量。如果OrderService只是协调订单流程并调用独立的日志、邮件组件,并不必然违反该原则;平台结论按题干把这些具体职责都交给同一类的理解成立。

2024年下半年软件设计师基础知识真题(学员版)

本节已整理 13 条来源记录;题号沿用来源,答案与解析默认收起。

2024-11-student Q016

来源:第 16 题(原站入口)。

面向对象软件测试中,检验一组协同工作的类之间的相互作用,属于哪个测试层次( )?

  • A.

    算法

  • B.

    系统

  • C.

    类

  • D.

    模板

答案与解析

平台答案:D。

整理解析

平台答案为D。题设描述的是类之间协作的集成测试层次:单类测试关注类内部,系统测试关注整个系统;一组协作类的交互则应在类之间的组合层次验证。

补充与纠错

原页截图已核实:四个选项依次为“算法、系统、类、模板”,平台答案为D。“模板”是原题用词,此处原样保留。题意属于一组协作类的集成测试;若教材使用“模块层/类簇层”术语,应与此含义对照,不应解释为C++模板机制测试。

2024-11-student Q030

来源:第 30 题(原站入口)。

要为业务流程建模,最适合使用下列哪种UML图( )?

  • A.

    交互图

  • B.

    活动图

  • C.

    部署图

  • D.

    用例图

答案与解析

平台答案:B。

整理解析

选B。活动图可表现业务活动的先后、分支、合并和并发流程。交互图侧重参与者间消息,用例图说明外部参与者与系统功能,部署图表现软硬件部署。

2024-11-student Q038

来源:第 38 题(原站入口)。

开放—封闭原则要求面向对象系统的软件实体(类、模块、函数)如何设计( )?

  • A.

    对扩展开放,对修改封闭

  • B.

    对继承开放,对组合封闭

  • C.

    对组合开放,对继承封闭

  • D.

    对修改开放,对扩展封闭

答案与解析

平台答案:A。

整理解析

选A。通过增加实现或组合等方式扩展行为,尽量维持既有实体稳定,符合“对扩展开放,对修改封闭”。它不是禁止修复已有缺陷,也不等于单纯偏好继承或组合。

2024-11-student Q039

来源:第 39 题(原站入口)。

UML用例图包含用例、参与者及其关系。哪种关系既能出现在两个用例之间,也能出现在两个参与者之间( )?

  • A.

    扩展

  • B.

    泛化

  • C.

    关联

  • D.

    包含

答案与解析

平台答案:B。

整理解析

选B。泛化表达一般与特殊:参与者可特化另一个参与者,用例也可特化另一个用例。包含、扩展用于用例之间,关联通常描述参与者与用例之间的交互。

2024-11-student Q049

来源:第 49 题(原站入口)。

面向对象方法中,对象的( )包含它的全部属性(通常是静态的),以及各属性的当前值(通常是动态的)。

  • A.

    行为

  • B.

    状态

  • C.

    语义

  • D.

    标识

答案与解析

平台答案:B。

同题对照:标准题。来源选项→标准题选项:A→C,B→A,C→D,D→B。

映射后平台答案:A。

重复判断依据

两题完整定义相同:对象的全部属性(通常静态)加当前属性值(通常动态)。四项行为、状态、语义一致;面向对象语境中的标识与唯一ID均为区别实例的对象身份,不增加业务条件。

补充与纠错

题干“通常是静态的属性”指属性描述相对稳定,并非要求使用static类成员;“动态值”指实例当前取值可改变。

2024-11-student Q052

来源:第 52 题(原站入口)。

从下列UML状态图的起始点出发,哪一事件序列会使状态机“卡住无法继续”( )?

  • A.

    b

  • B.

    a->d

  • C.

    a->e->b

  • D.

    其他选项都会

答案与解析

平台答案:D。

整理解析

平台答案D。把图中左上、下方、右上状态分别临时记为S、T、R:b使S到R;a→d使S经T到R;a→e→b使S经T回S后到R。三条序列都进入只有c自环的R,无法再到图中的终态,所以按平台意图选D。

补充与纠错

“卡住无法继续”不是严格说法:右上状态仍有c自环,可继续响应c事件,只是图中没有从它到终态的路径。平台D按“无法到达终态”理解,不能据此断言该状态完全没有迁移或已经死锁。

2024-11-student Q060

来源:第 60 题(原站入口)。

软件需要显示计算机(Computer)及其Keyboard、Mouse、Monitor部件,类设计见下图。它采用( 60 )模式,归入( 61 )模式,适用情形为( 62 );显示操作的具体实现者是( 63 )。

请作答:第60题。

  • A.

    访问者(Visitor)

  • B.

    观察者(Observer)

  • C.

    中介署(Mediator)

  • D.

    命令(Command)

答案与解析

平台答案:A。

整理解析

选A。部件提供accept,内部再调用传入对象的display(this);Display针对不同部件类型定义显示操作,ComputerPartDisplay给出具体实现。这是访问者模式把一组操作从元素结构中分离的典型协作。

补充与纠错

原C项“中介署(Mediator)”照录;通常译为“中介者”。访问者便于添加操作,但若新增元素种类,往往需要扩展访问者接口及相关实现,不能说所有扩展都无需改原类。

2024-11-student Q061

来源:第 61 题(原站入口)。

软件需要显示计算机(Computer)及其Keyboard、Mouse、Monitor部件,类设计见下图。它采用( 60 )模式,归入( 61 )模式,适用情形为( 62 );显示操作的具体实现者是( 63 )。

请作答:第61题。

  • A.

    对象结构型

  • B.

    类结构型

  • C.

    对象行为型

  • D.

    类行为型

答案与解析

平台答案:C。

整理解析

选C。访问者通过元素对象与访问者对象的协作完成操作,归入对象行为型模式。判断类别应看职责与协作方式,不能因为图中存在继承箭头就认作类结构型。

2024-11-student Q062

来源:第 62 题(原站入口)。

软件需要显示计算机(Computer)及其Keyboard、Mouse、Monitor部件,类设计见下图。它采用( 60 )模式,归入( 61 )模式,适用情形为( 62 );显示操作的具体实现者是( 63 )。

请作答:第62题。

  • A.

    当一个对象必须通知其他对象,而它又不能假定其他对象是谁

  • B.

    抽象出待执行的动作以参数化某对象

  • C.

    一个对象结构包含很多类对象,它们有不同的接口,而用户想对这些对象实施一些依赖于其具体类的操作

  • D.

    想定制一个分布在多个类中的行为,而又不想生成太多的子类

答案与解析

平台答案:C。

整理解析

选C。对象结构中包含不同具体类,操作又依赖各元素的类型,访问者可把相关操作集中到一个访问者中。A是观察者的典型场景,B对应命令;D更接近中介者通过集中交互来定制跨多个类的行为。

补充与纠错

平台把D解释成模板方法或策略不够准确;“定制分布在多个类中的行为,又不生成太多子类”是中介者的常见适用描述。判断本题仍以类图中的accept/display协作和C的具体类操作需求为准。

2024-11-student Q063

来源:第 63 题(原站入口)。

软件需要显示计算机(Computer)及其Keyboard、Mouse、Monitor部件,类设计见下图。它采用( 60 )模式,归入( 61 )模式,适用情形为( 62 );显示操作的具体实现者是( 63 )。

请作答:第63题。

  • A.

    ComputerPartDisplay

  • B.

    Computer

  • C.

    ComputerPart

  • D.

    Display

答案与解析

平台答案:A。

整理解析

选A。Display声明操作,ComputerPart声明accept,Computer等是被访问的元素;ComputerPartDisplay实现Display并提供各类部件的显示逻辑,所以它才是显示操作的具体实现者。

2024-11-student Q073

来源:第 73 题(原站入口)。

UML活动图中的以下符号为( 73 ),用来分组活动状态。

UML序列图用于建模( 74 )。根据下面的活动图,序列图( 75 )不能由它得到。

请作答:第73题。

  • A.

    操作

  • B.

    活动

  • C.

    泳道

  • D.

    判定

答案与解析

平台答案:C。

整理解析

选C。泳道把活动按责任主体或参与对象分区,图中a:A、b:B、c:C各自承担本分区内的动作。它不是表示条件判断的菱形,也不是单个操作节点。

2024-11-student Q074

来源:第 74 题(原站入口)。

UML活动图中的以下符号为( 73 ),用来分组活动状态。

UML序列图用于建模( 74 )。根据下面的活动图,序列图( 75 )不能由它得到。

请作答:第74题。

  • A.

    一个特定对象的状态以及引起状态转换的事件

  • B.

    系统内从一个活动到另一个活动的流程

  • C.

    某一时刻一组对象以及它们之间的关系

  • D.

    以时间顺序组织的对象之间的交互活动

答案与解析

平台答案:D。

整理解析

选D。序列图沿时间顺序描述参与对象之间的消息交互。A描述状态机图,B描述活动图,C描述对象图所表示的某一时刻实例及其关系。

2024-11-student Q075

来源:第 75 题(原站入口)。

UML活动图中的以下符号为( 73 ),用来分组活动状态。

UML序列图用于建模( 74 )。根据下面的活动图,序列图( 75 )不能由它得到。

请作答:第75题。

  • A.

  • B.

  • C.

    其他选项都能

  • D.

答案与解析

平台答案:D。

整理解析

平台答案D。活动图中a调用b.x(i),b在i≤0时返回0;i>0时调用c.y(i)取得4i再返回给a,最后由a执行print(n)。图D的x(-1)返回0正确,但随后print(0)画成a发给b的消息,把本应由a执行的操作交给了b,责任主体不符。

补充与纠错

平台所说“print之后直接结束、不再指向B”没有抓住错误,应检查print消息的接收者。原A图第三消息确写“3:prain(4)”,与活动图的print(n)不一致,属于原图笔误,照原图保留。A未显示c生命线,B未画最终print,原题也没有允许局部视图或省略消息的额外约定,因此不能断言其他图都严格完整地对应活动图。保留平台D,并说明这些原题缺陷,不猜改图片。

2024年下半年软件设计师案例分析真题:案例题

本节收录 3 组案例。

2024-11-case Q003

智能交通管理系统的 UML 分析与设计

(三)(15分)

【说明】

某城市计划开发一个智能交通管理系统,实时监控并优化城市的交通流量。该系统的主要功能描述如下:

(1)交通流量监控(TrafficMonitor)。系统将从各种传感器(Sensor)(如路面摄像头、车辆GPS设备、交通信号灯等)收集交通数据。交警根据这些数据进行实时分析,预测交通拥堵,优化交通信号灯(TrafficLightOptimizer)的配时。

(2)公共交通管理(PublicTransportManager)。系统需管理和优化公共交通工具(Public Transport)(如公交车(Bus)、地铁(Subway)等)的调度,公交调度员根据实时路况和乘客需求调整路线和班次。

(3)应急响应管理(EmergencyRespoaseCoordinator)。在发生交通事故或者其他突发事件时,系统需要通知相关应急响应部门并给出最优的应急方案。同时,系统还需重新设计和发布新的交通路线,以避开事故区域。

(4)智能停车管理。系统将帮助驾驶者实时找到附近的停车位,并提供导航服务。还能进行停车费用的自动支付和账单管理。

采用面向对象分析与设计方法开发上述系统,得到如图1所示的用例图以及图2所示的初始类图(部分)。

01(8分)
根据说明中的描述,给出图1中A1A3所对应的参与者名称和U1U5处所对应的用例名称。
02(4分)
根据说明中的描述,给出图2中C1~C4所对应的类名。
03(3分)
在应急响应管理功能中,需要根据事件的严重程度和优先级,按照应急事件的处理流程,逐步将处理任务分配给合适的应急响应单位。请用文字说明哪种设计模式适合于实现该需求并简单说明原因?

答案与解析

平台参考答案(原意保留)

平台参考答案(保留原意):

  1. A1 交警;A2 调度员;A3 应急响应部门。U1 收集分析交通数据;U2 预测交通拥堵;U3 优化交通信号灯配时;U4 管理优化公共交通工具;U5 获取通知以及最优应急方案。
  2. C1 TrafficMonitor;C2 Sensor;C3 PublicTransportManager;C4 PublicTransport。
  3. 责任链模式。平台解释为级联处理请求,可以灵活组织处理链,直到某一级处理完就停止传递,适应性强。

解析与纠错

解析与纠错:

  • A1 与数据分析、拥堵预测、信号灯配时用例相连,符合交警职责;A2 对应公共交通调度员;A3 与应急方案、新路线发布等用例相连,符合应急响应部门。U1 同时与传感器相连,其余用例填法可按平台答案理解。图1未提供进一步区分 U2 与 U3 的条件;“预测交通拥堵”“优化交通信号灯配时”分占二者是平台给出的排列,题干语义和所示连线本身不足以唯一确定二者的上下顺序。
  • 图中的 «extend» 箭头从扩展用例指向被扩展的基本用例。它表示满足扩展条件时插入行为,不能解释成“先做 U1,之后必做 U2/U3”的顺序流程,也不能据此把所有应急功能都归入公共交通管理。平台解析以业务先后顺序解释扩展关系,表述不严谨;填写用例名称时,还应区分既有关系图的准确语义。
  • 根据功能与关联,C1 是交通流量监控,C2 是传感器,C3 是公共交通管理,C4 应是公共交通工具。关联本身不能直接等同于所有权。
  • 已核查图2:Bus、SubWay 附近的空心三角箭头实际指向这两个类,而题意要求 Bus、Subway 是 PublicTransport 的子类。按 UML,泛化箭头应指向父类 C4,现有图片方向与题意相反。图中的箭头方向与题意冲突,类名按需求语义填写。
  • 图2的空心菱形位于 EmergencyResponseCoordinator 一端,表达该端聚合 C1/C3,而非平台解析所说的“C1 聚合应急响应协调器”。题干文字另拼为 EmergencyRespoaseCoordinator,图中为 EmergencyResponseCoordinator,Subway/SubWay 也有大小写差异;两处资料的拼写并不一致。
  • 按严重程度、优先级逐级选择合适响应单位,责任链模式能让各处理者判断是否处理、转交或在处理后继续传递,避免请求发起方绑定某个具体单位。“处理后立即停止”是常见实现,并非模式的强制规则;若业务要求多个单位接续协作,需要明确转交条件、终止条件及无人能处理时的处理方式。

2024-11-case Q005

C++ 图形编辑器的组合模式填空

(五)(15分)

【说明】

某图形编辑器能够处理不同类型的图形,包括基本图形(如圆形、矩形等)和复合图形(由多个基本图形组合而成)。在该编辑器中用户能够以统一的方式操作单个图形和复合图形,例如,能够对它们进行绘制、移动和删除等操作。现采用组合(Composite)模式实现上述要求,得到如图1所示的类图。

【C++代码】

#include <iostream>
#include <list>
#include <string>
using namespace std;
//抽象组件类
class GraphicElement {
    protected:
    (1);
    public:
    (2);
    (3);
}
//基本图形
class Circle: public GraphicElement {
    private:
    int radius;
    public:
    Circle(const string& name, int radius){
        this->name = name; this->radius = radius;
    }
    void draw(){
        cout << "Drawing Circle:" << name << endl;
    }
    void move(int dx, int dy) {
        cout << "Moving Circle:" << name << "by (" << dx << "," << dy << ")" << endl;
    }
};
//复合图形
class CompositeGraphic: public GraphicElement {
    private:
    (4);
    public:
    CompositeGraphic(const string& name) {this->name = name;}
    void add(GraphicElement* elem) { elements.push_back(elem); }
    void remove(GraphicElement* elem) { elements.remove(elem); }
    void draw(){
        cout << "Drawing CompositeGraphic:" << name << endl;
    }
    void move(int dx, int dy){
        cout << "Moving CompositeGraphic:" << name << " by (" << dx << "," << dy << ")" << endl;
    }
};
int main(){
    (5);
    Circle circle1("Circle1", 10);
    Circle circle2("Circle2", 20);
    graphic.add(&circle1);
    graphic.add(&circle2);
    graphic.draw();
    graphic.move(5, 5);
    return 0;
}

01(15分)
阅读说明和C++代码,将应填入(1)~(5)处的程序补充完整。

答案与解析

平台参考答案(原意保留)

平台参考答案(仅五处填空):

  1. string name
  2. virtual void draw() = 0
  3. virtual void move(int dx, int dy) = 0
  4. list<GraphicElement*> elements
  5. CompositeGraphic graphic("Composite1")

解析与纠错

解析与纠错:

  • GraphicElement 定义共同操作,Circle 是叶子组件,CompositeGraphic 保存组件指针列表。protected 的 name 可供派生类使用;两个纯虚函数使基类成为抽象类;容器元素类型为基类指针,既可容纳圆形也可容纳复合图形。平台五处填空与题目声明位置相符,末尾分号已由模板给出。
  • 题干的 class GraphicElement 以 } 结束,缺少 C++ 类定义必需的分号。即使五空全部填入,仍不能编译。完整实现需将类体结尾补为 };。
  • 原来的 CompositeGraphic::draw 与 move 只打印自身名称,没有遍历 elements,因此不会绘制/移动任何子组件。实际运行计数探针确认:调用复合对象一次 draw 和一次 move,子节点的两种调用次数均为0。填空本身不能解决这项功能缺口,需在方法内遍历并分别调用 elem->draw() 和 elem->move(dx, dy)。
  • 通过基类指针调用虚函数,可递归处理复合子节点,这才支持对一组图形统一操作。移动参数必须原样传入子组件。
  • 题目中的 remove 仅从组合容器移除该指针;它不释放图形对象。主函数里的 Circle 在栈上,不能据此执行 delete。完整示例采用不拥有子对象的指针列表,并增加虚析构函数;对象释放和坐标维护不属于给定五空的内容。draw/move 仍以输出代表操作,验证的是调用传播,不是实际图形渲染。

C++17 编译和测试通过:空组合、基类指针调用、直接与嵌套子节点、移动参数传递、移除叶子/子组后停止调用。

补充与完整修正示例

完整修正示例:

示例补齐分号并在组合方法中委派调用。容器中的指针不拥有子对象;子对象在访问期间必须有效,且不允许空指针或组合环。

#include <iostream>
#include <list>
#include <string>
using namespace std;

class GraphicElement {
protected:
    string name;
public:
    virtual ~GraphicElement() = default;
    virtual void draw() = 0;
    virtual void move(int dx, int dy) = 0;
};

class Circle : public GraphicElement {
private:
    int radius;
public:
    Circle(const string& name, int radius) { this->name = name; this->radius = radius; }
    void draw() override { cout << "Drawing Circle:" << name << endl; }
    void move(int dx, int dy) override {
        cout << "Moving Circle:" << name << " by (" << dx << "," << dy << ")" << endl;
    }
};

class CompositeGraphic : public GraphicElement {
private:
    list<GraphicElement*> elements; // 不拥有子对象,子对象必须比此引用活得更久。
public:
    explicit CompositeGraphic(const string& name) { this->name = name; }
    void add(GraphicElement* elem) { elements.push_back(elem); }
    void remove(GraphicElement* elem) { elements.remove(elem); }
    void draw() override {
        cout << "Drawing CompositeGraphic:" << name << endl;
        for (GraphicElement* elem : elements) elem->draw();
    }
    void move(int dx, int dy) override {
        cout << "Moving CompositeGraphic:" << name << " by (" << dx << "," << dy << ")" << endl;
        for (GraphicElement* elem : elements) elem->move(dx, dy);
    }
};

#ifndef COMPOSITE_NO_MAIN
int main() {
    Circle circle1("Circle1", 10), circle2("Circle2", 20);
    CompositeGraphic graphic("Composite1");
    graphic.add(&circle1);
    graphic.add(&circle2);
    graphic.draw();
    graphic.move(5, 5);
    return 0;
}
#endif

2024-11-case Q006

Java 图形编辑器的组合模式填空

(六)(15分)

【说明】

某图形编辑器能够处理不同类型的图形,包括基本图形(如圆形、矩形等)和复合图形(由多个基本图形组合而成)。在该编辑器中用户能够以统一的方式操作单个图形和复合图形,例如,能够对它们进行绘制、移动和删除等操作。现采用组合(Composite)模式实现上述要求,得到如图1所示的类图。

【Java代码】

import java.util.ArrayList;
import java.util.*;
// 抽象图形元素父类
abstract class GraphicElement {
    protected (1);
    public (2);
    public (3);
}
// 基本图形:圆形
class Circle extends GraphicElement {
    private int radius;
    public Circle(String name, int radius) {
        this.name = name;
        this.radius = radius;
    }
    public void draw() {
        System.out.println("Drawing Circle:" + name);
    }
    public void move(int dx, int dy) {
        System.out.println("Moving Circle:" + name + "by(" + dx + "," + dy + ")");
    }
}
// 复合图形
class CompositeGraphic extends GraphicElement {
    private (4);
    public CompositeGraphic(String name) {
        this.name = name;
        elements = new ArrayList
    }
    public void add(GraphicElement elem) {
        elements.add(elem);
    }
    public void remove(GraphicElement elem) {
        elements.remove(elem);
    }
    public void draw() {
        System.out.println("Drawing CompositeGraphic:" + name);
    }
    public void move(int dx, int dy) {
        System.out.println("Drawing CompositeGraphic:" + name + "by(" + dx + "," + dy + ")");
    }
}
// 测试类
class CompositePatternTest {
    public static void main(String[] args) {
        (5);
        Circle circle1 = new Circle("Circle1", 10);
        Circle circle2 = new Circle("Circle2", 20);
        graphic.add(circle1);
        graphic.add(circle2);
        graphic.draw();
        graphic.move(5,5);
    }
}

01(15分)
阅读说明和Java代码,将应填入(1)~(5)处的程序补充完整。

答案与解析

平台参考答案(原意保留)

平台参考答案(保留原始表达):

  1. String name;
  2. abstract void draw();
  3. abstract void move(int dx, int dy);
  4. List<GraphicElement> elements; 或 ArrayList<GraphicElement> elements
  5. CompositeGraphic graphic = new CompositeGraphic(“Group1”);

上述中文弯引号及分号是平台答案中的写法,不代表可不加处理地原样粘贴编译。

解析与纠错

解析与纠错:

  • GraphicElement 用抽象方法约定操作,Circle 与 CompositeGraphic 通过继承获得共同接口,List/ArrayList 存放 GraphicElement 引用。若按题干自带的分号填空,可填写:String name、abstract void draw()、abstract void move(int dx, int dy)、List<GraphicElement> elements、CompositeGraphic graphic = new CompositeGraphic("Group1")。声明处使用 List 或 ArrayList 均可与 ArrayList 实例兼容,前者较少依赖具体实现。
  • 原题构造函数只显示 elements = new ArrayList。原页已确认这一缺损,原题缺少 <>();。仅填写五空无法让这个代码片段通过 Java 编译。完整修正版使用 elements = new ArrayList<>();。这是额外的语法修复,不是某一空的答案。
  • 平台(5)的中文弯引号 “ ” 不是 Java 字符串定界符;代码中需使用 ASCII 双引号。Group1 只是对象名称,题干并未规定一定要使用它。平台答案部分空带分号,题干又自带分号,填入时可去掉重复的末尾分号;多出的空语句不构成此次核心故障。
  • 与 C++ 题一样,原始 draw/move 只打印复合对象,没有调用子组件,不能完成组合操作的传播。只修复构造语句后,子节点调用探针依然失败。应遍历 elements,分别调用每个子对象的 draw 或 move;嵌套组合也会由多态调用继续向下传递。
  • 原始 move 的日志文案也写成了 Drawing CompositeGraphic,完整示例改为 Moving CompositeGraphic。remove 只从集合解除引用,Java 的垃圾回收不等于立即销毁对象;题干未给出额外资源释放协议。示例仍用日志表示绘制/移动,不声称实现了真实坐标变化。

Java 21 编译和测试通过:空组合、基类引用调用、直接与嵌套子节点、移动参数传递、移除叶子/子组后停止调用。

补充与完整修正示例

完整修正示例:

示例补齐构造语句、委派子组件操作并修正移动日志。列表不得包含 null,组合结构不得形成环。代码文件名为 CompositePatternTest.java。

import java.util.ArrayList;
import java.util.List;

abstract class GraphicElement {
    protected String name;
    public abstract void draw();
    public abstract void move(int dx, int dy);
}

class Circle extends GraphicElement {
    private final int radius;
    public Circle(String name, int radius) { this.name = name; this.radius = radius; }
    @Override public void draw() { System.out.println("Drawing Circle:" + name); }
    @Override public void move(int dx, int dy) {
        System.out.println("Moving Circle:" + name + " by (" + dx + "," + dy + ")");
    }
}

class CompositeGraphic extends GraphicElement {
    private final List<GraphicElement> elements;
    public CompositeGraphic(String name) {
        this.name = name;
        elements = new ArrayList<>();
    }
    public void add(GraphicElement elem) { elements.add(elem); }
    public void remove(GraphicElement elem) { elements.remove(elem); }
    @Override public void draw() {
        System.out.println("Drawing CompositeGraphic:" + name);
        for (GraphicElement elem : elements) elem.draw();
    }
    @Override public void move(int dx, int dy) {
        System.out.println("Moving CompositeGraphic:" + name + " by (" + dx + "," + dy + ")");
        for (GraphicElement elem : elements) elem.move(dx, dy);
    }
}

public class CompositePatternTest {
    public static void main(String[] args) {
        CompositeGraphic graphic = new CompositeGraphic("Group1");
        Circle circle1 = new Circle("Circle1", 10), circle2 = new Circle("Circle2", 20);
        graphic.add(circle1);
        graphic.add(circle2);
        graphic.draw();
        graphic.move(5, 5);
    }
}

2024年上半年软件设计师考试综合知识(专业解析+参考答案)

本节已整理 13 条来源记录;题号沿用来源,答案与解析默认收起。

2024-05 Q017

来源:第 17 题(原站入口)。

【考生回忆版】UML类图提供系统的静态设计视图。表示两类事物之间特殊/一般关系,应采用( )关系。

  • A.

    聚合

  • B.

    依赖

  • C.

    泛化

  • D.

    实现

答案与解析

平台答案:C。

整理解析

选C。泛化连接一般的父类与更特殊的子类,表达is-a关系。聚合侧重整体与部分,依赖表示使用关系,实现表示满足某项规格或契约,均不是这里的特殊/一般关系。

补充与纠错

实现关系不只限于具体类和接口,聚合也不能简单用“生命周期必定不同”来定义;本题按一般与特殊这一直接线索判断泛化。

2024-05 Q020

来源:第 20 题(原站入口)。

【考生回忆版】面向对象软件可分层测试。其中( )层逐一测试类中定义的方法,相当于传统软件测试中的单元测试。

  • A.

    模板

  • B.

    系统

  • C.

    类

  • D.

    算法

答案与解析

平台答案:D。

整理解析

选D。按题目采用的四层测试划分,算法层针对单个方法的处理逻辑;类层检查同一类的方法与属性协作,模板层检查一组类的协作,系统层检查完整系统。

补充与纠错

算法层、类层、模板层、系统层属于题目采用的教材划分;实际测试工具对“单元”的边界可能不同,不应认为所有面向对象测试只能按这四个固定名称组织。

2024-05 Q023

来源:第 23 题(原站入口)。

【考生回忆版】面向对象系统设计中,包A依赖包B,包B依赖包C,包C又依赖包A,这违反了( )原则。

  • A.

    稳定抽象

  • B.

    稳定依赖

  • C.

    依赖倒置

  • D.

    无环依赖

答案与解析

平台答案:D。

整理解析

选D。依赖关系A→B→C→A构成有向环,直接违反无环依赖原则。依赖倒置关注依赖抽象而非具体实现,稳定依赖与稳定抽象分别关注依赖方向和抽象程度,并非本题识别这个环的名称。

2024-05 Q027

来源:第 27 题(原站入口)。

【考生回忆版】进行面向对象设计时,以下哪项不能作为继承的类型( )?

  • A.

    多重继承

  • B.

    分布式继承

  • C.

    单重继承

  • D.

    层次继承

答案与解析

平台答案:B。

整理解析

选B。“分布式继承”不是这里通常采用的继承分类。单重继承指一个直接父类,多重继承指多个直接父类;层次继承通常指一个基类派生多个子类的层次结构。

补充与纠错

平台把层次继承解释为“继承类并实现接口”不准确,两者不是同一分类标准。不同语言对多重类继承的支持也不同,不能说所有面向对象语言都直接支持它。

2024-05 Q032

来源:第 32 题(原站入口)。

【考生回忆版】用面向对象方法建模机器人(Robot)的移动行为,得到如下UML模型。该图为UML( 32 ),展示了机器人( 33 )。

请作答:第32题。

  • A.

    类图

  • B.

    对象图

  • C.

    组件图

  • D.

    部署图

答案与解析

平台答案:B。

整理解析

选B。a1:Area、a2:Area等是具体实例,墙对象还有width=20或24的具体属性值,图中连线表示这些实例之间的链接,因此是对象图,不是只描述类及关联的类图。

补充与纠错

题图部分实例标记和下划线不够规范,仍应结合a1:Area、a2:Area及width的具体取值理解其对象快照意图;不自行重绘或补改图。

2024-05 Q033

来源:第 33 题(原站入口)。

【考生回忆版】用面向对象方法建模机器人(Robot)的移动行为,得到如下UML模型。该图为UML( 32 ),展示了机器人( 33 )。

请作答:第33题。

  • A.

    Robot移动的状态、转换、事件和移动的状态机

  • B.

    Robot、World、Area、Wall构件之间的组织和依赖

  • C.

    Robot、World、Area、Wall类及其之间的关联关系

  • D.

    Robot类的对象r移动到某一时刻与World、Area、Wall类型的对象及其之间关系的静态快照

答案与解析

平台答案:D。

整理解析

选D。图中展示Robot实例r与World、Area、Wall实例及具体取值,反映某一时刻的对象快照。它没有展开移动事件与状态转换,也不是组件依赖或运行节点部署视图。

2024-05 Q039

来源:第 39 题(原站入口)。

【考生回忆版】下面UML活动图中,圈1处的◇表示( 39 ),圈2处的符号表示( 40 )。该图中不可能的活动顺序是( 41 )。

请作答:第39题。

  • A.

    并发汇合

  • B.

    合并

  • C.

    并发分岔

  • D.

    分支

答案与解析

平台答案:D。

整理解析

选D。圈1是一个输入、两个输出的菱形,表示按条件选择后续路径的分支(决策)节点;它与多条互斥路径进入一个出口的合并节点方向相反。两条并发路径则由后面的长条分出。

补充与纠错

图中各分支未标出监护条件,起点画法也不规范,但圈1的一入多出结构足以识别其决策用途。保留原图及原空39、40、41,不在本题回填其他小问答案。

2024-05 Q040

来源:第 40 题(原站入口)。

【考生回忆版】下面UML活动图中,圈1处的◇表示( 39 ),圈2处的符号表示( 40 )。该图中不可能的活动顺序是( 41 )。

请作答:第40题。

  • A.

    并发汇合

  • B.

    并发分岔

  • C.

    合并

  • D.

    分支

答案与解析

平台答案:A。

整理解析

选A。圈2的长条有两个输入和一个输出,是并发汇合(join),按默认语义等待各输入分支到达后才能继续Act5;合并(merge)使用菱形,用于互斥分支汇入,不负责等待所有分支。

补充与纠错

平台把“Act3→Act4→Act5”列为可独立完成的路径,遗漏了并发支Act2,按默认join语义不成立。进入分岔后,Act2与下方分支都须完成;下方可绕过Act3/Act4,但Act2不能被省略。按Act1直达终态则是圈1选择的另一条互斥路线。第41题由另一分区审校,本题不替它作答。

2024-05 Q041

来源:第 41 题(原站入口)。

UML活动图如下。圈1的◇表示(39),圈2表示(40)。下列选项中,不可能的活动顺序是(41)。

请作答:第41题。

  • A.

    Act2 -> Act3 -> Act4 -> Act5

  • B.

    Act2 -> Act5

  • C.

    Act3 -> Act4 -> Act5

  • D.

    Act1

答案与解析

平台答案:A。

整理解析

平台答案A。若只沿图上一条有向路线追踪,Act2之后没有通向Act3的边,因此平台排除了Act2→Act3→Act4→Act5;Act1可直接结束,另两条图上路线可到Act5。

补充与纠错

纠错:完整活动执行不能简单等同于图上的一条路线。左侧竖条并发启动Act2与下方分支,右侧竖条等待两支到达;下方选择Act3→Act4时,Act2先完成、随后Act3和Act4完成、最后Act5,是允许的先后顺序,A并非不可能。若选项表示完整执行轨迹,C又遗漏了必需的Act2。原页已核实,题干确未限定单条路线,也没有额外并发约定;这是原题表述与平台判法的冲突,保留平台A及原图。

2024-05 Q042

来源:第 42 题(原站入口)。

某多媒体系统需要播放多种格式的视频,各格式有相应的解码器、渲染器等实现。为了按播放格式完成解码转换,系统提供统一的简单接口VideoConverter,设计见类图。该设计采用(42)模式,其意图为(43);其中(44)了解各解码程序的职责,并将客户的转换请求转交给适当的解码器;该模式属于(45)。

请作答:第42题。

  • A.

    代理(Proxy)

  • B.

    桥接(Bridge)

  • C.

    适配器(Adapter)

  • D.

    外观(Facade)

答案与解析

平台答案:D。

整理解析

选D。客户只调用VideoConverter,由它协同解码、码率处理和音频处理等子系统对象;以一个高层入口简化子系统使用,符合外观模式。图的重点不是替代某一对象控制访问,也不是解决两个不兼容接口或拆分两个独立变化维度。

2024-05 Q043

来源:第 43 题(原站入口)。

某多媒体系统需要播放多种格式的视频,各格式有相应的解码器、渲染器等实现。为了按播放格式完成解码转换,系统提供统一的简单接口VideoConverter,设计见类图。该设计采用(42)模式,其意图为(43);其中(44)了解各解码程序的职责,并将客户的转换请求转交给适当的解码器;该模式属于(45)。

请作答:第43题。

  • A.

    为子系统中的一组接口提供一个一致的界面,定义了一个高层接口,这个接口使得这一子系统更加容易使用

  • B.

    将一个类的接口转换成客户希望的另外一个接口

  • C.

    为其他对象提供一种代理以控制对这个对象的访问

  • D.

    将抽象部分与其实现部分分离,使它们都可以独 立地变化

答案与解析

平台答案:A。

整理解析

选A。VideoConverter把多个底层处理入口组织成客户可直接使用的高层接口。其余三项分别描述适配器的接口转换、代理的访问控制、桥接的抽象与实现分离。

2024-05 Q044

来源:第 44 题(原站入口)。

某多媒体系统需要播放多种格式的视频,各格式有相应的解码器、渲染器等实现。为了按播放格式完成解码转换,系统提供统一的简单接口VideoConverter,设计见类图。该设计采用(42)模式,其意图为(43);其中(44)了解各解码程序的职责,并将客户的转换请求转交给适当的解码器;该模式属于(45)。

请作答:第44题。

  • A.

    CodeC

  • B.

    BitrateReader

  • C.

    CodecFactory

  • D.

    VideoConverter

答案与解析

平台答案:D。

整理解析

选D。图中Application直接指向VideoConverter;后者向AudioMixer、BitrateReader及CodecFactory等分派协作任务,是客户与子系统之间的统一入口。CodecFactory负责取得编解码器,不能因此替代整个外观对象的协调职责。

2024-05 Q045

来源:第 45 题(原站入口)。

某多媒体系统需要播放多种格式的视频,各格式有相应的解码器、渲染器等实现。为了按播放格式完成解码转换,系统提供统一的简单接口VideoConverter,设计见类图。该设计采用(42)模式,其意图为(43);其中(44)了解各解码程序的职责,并将客户的转换请求转交给适当的解码器;该模式属于(45)。

请作答:第45题。

  • A.

    对象创建型模式

  • B.

    类创建型模式

  • C.

    类结构型模式

  • D.

    对象结构型模式

答案与解析

平台答案:D。

整理解析

选D。外观以对象协作组织对子系统的访问,按GoF分类属于对象结构型模式。创建型关注对象的产生;类结构型主要借助继承安排类之间的结构关系。

2024年上半年软件设计师应用技术真题(专业解析+参考答案):案例题

本节保留 3 条来源:2 组完整,1 组不完整。

2024-05-case Q002

在线教育平台的用例、类与分析设计模型

阅读下列说明和图,回答问题。

【说明】

某公司预开发一个在线教育平台。学生(Student)可以在该平台上注册账户、浏览课程、购买课程、学习课程内容、参与课程讨论、提交作业、获得成绩反馈;教师(Teacher)可以创建课程、发布课程内容、批改作业、与学生互动并提供成绩反馈。该平台的主要功能描述如下:

(1)用户(User)注册与登录。学生、教师在平台上填写个人信息进行注册。注册成功后,可以使用平台生成的账户登录平台。用户可以修改个人信息,也可以注销自己的账户。

(2)浏览与购买课程(Course)。学生登录平台后,可以浏览不同课程的详细信息,包括课程简介、课程目标、授课内容说明等。学生可以购买课程,购买后可以获得访问课程内容的权限。

(3)学习课程内容(Content)。对于已经购买的课程,学生可以在平台上观看该课程的教学视频、下载教学材料、参加在线测试。

(4)参与课程讨论(Discussion)。学生可以参与已购买课程的课程论坛,在论坛中提问、回复其他人的问题、查看讨论记录。课程论坛由教授该课程的教师维护。

(5)提交作业(Assignment)。学生通过平台提交已购买课程的作业。

(6)获取成绩反馈(Grade)。授课教师在平台上批改学生提交的作业,并给出成绩和反馈意见。学生可以在平台上查看教师的反馈。

现在采用面向对象方法实现该线上教育平台,得到如图1所示的用例图和图2所示的初始类图。

01(7分)

根据说明中的描述,给出图1中A1A3所对应的参与者名称以及U1U4所对应的用例名。

02(6分)
根据说明中的描述,给出图2中C1~C6所对应的类名。

03(2分)
在基于模型驱动的软件开发方法中,在分析阶段和设计阶段通常会使用不同的模型。面向对象方法作为典型的模型驱动开发方法,在分析阶段和设计阶段分别使用的是哪种模型?这两个阶段的模型有何区别?

答案与解析

平台参考答案(原意保留)

平台参考答案:

  1. A1 User;A2 Teacher;A3 Student。U1 登录;U2、U4 分别为参与课程讨论和获取成绩反馈,两者可交换;U3 购买课程。
  2. C1 User;C2、C3 分别为 Student、Teacher,两者可交换;C4 Course;C5 Assignment;C6 Grade。
  3. 平台认为分析阶段使用用例模型,设计阶段使用类图模型:用例模型描述功能需求、系统行为及参与者交互;类图模型描述类、接口、关联和继承等静态结构,为设计实现提供指导。

解析与纠错

解析与纠错:

  • A1 是学生和教师共同的用户角色;A3 与浏览、购买、学习课程、提交作业关联,因此为 Student;A2 为 Teacher。图中两个位置都标为 A2,表示同一教师角色的重复绘制,不是新增一种参与者。
  • 参与课程讨论和获取成绩反馈同时涉及学生、教师。U2、U4没有进一步区分语义的标注,因此二者可以交换。U3按说明对应购买课程。
  • C1是父类User,C2、C3是其两个子类Student、Teacher。图中两子类与Course的普通关联缺少进一步角色限定,二者可交换。C4与Content、Discussion、C5相连且菱形位于C4端,结合业务语义应为Course;C5为Assignment,C6为Grade。图中的实心菱形表示组合关系,而非普通关联。
  • 用例图中 «extend» 箭头指向被扩展的基本用例,不能表达“必须先注册再登录”或“必须先购买才能学习”的一般先后条件。已购课程是访问课程内容等功能的前置条件;并不意味着每次学习都触发一次购课行为。平台以这些前置条件直接解释扩展关系不够严谨。
  • 第3问的核心区别是 分析模型与设计模型的关注层次。分析模型描述问题域、业务概念、需求、对象职责与交互,侧重系统“需要做什么”;设计模型进一步确定软件类与接口、操作、协作、组件、数据结构和实现约束,侧重系统“如何实现”。设计模型通常由分析模型细化、补充并映射到技术方案。
  • 用例图和类图分别侧重行为需求与静态结构,但不能把“分析模型=用例模型、设计模型=类图模型”作为阶段的严格对应关系。分析阶段也会使用领域类图、交互图等;设计阶段也会使用设计类图、顺序图、状态图、组件图等。平台对两种图用途的介绍有参考价值,但不足以准确回答两个阶段模型的完整区别。

2024-05-case Q005

C++ 银行账户状态模式(题面代码不完整)

来源不完整:原页仅给出(1)处及前半段代码,缺少(2)—(5)的上下文。

阅读下列说明和C++代码,回答问题。
【说明】
在银行账户管理系统中,账户可以处于多种状态,如激活、冻结、注销等。在每个不同的状态下,都有特定的行为,例如激活状态的账户可以进行存款和取款操作,而冻结状态的账户则不能进行任何操作。现采用State(状态)模式实现上述场景,得到如图1所示的类图。

【C++代码】

#include < iostream >
using namespace std;
//账户状态接口
class AccountState {
public:
virtual void deposit(double amount) = 0;
virtual void withdraw(double amount)= 0;
virtual void freeze()= 0;
virtual void unfreeze()= 0;
};
//账户上下文
class Account {
private:
(1);
public:
Account(): state(NULL) {}
void setState(AccountState* state) {
this- > state = state;
代码不全

01(15分)
根据以上说明和C++代码,填充C++代码中的空(1)~(5)。

答案与解析

平台参考答案(原意保留)

暂无。

解析与纠错

原页已确认:题面仅出现(1),代码在 setState 中的 this- > state = state; 后终止,紧接原站“代码不全”,随后仍要求填写(1)—(5),参考答案为“暂无”。没有后续代码,(2)—(5)的上下文缺失,无法确定其填法。

从构造函数把 state 设为 NULL、setState 接收 AccountState 指针并赋给成员,可以确定(1)应为 AccountState* state。这是根据现有代码推导的结果,平台本题没有提供参考答案。

类图中 Account 是上下文,AccountState 是状态接口,ActiveState 与 FrozenState 是具体状态。上下文应把操作交给当前状态,冻结和解冻如果表示真正改变账户行为,还需要更新当前状态对象。完整C++代码缺失,无法验证五个填空、状态转换或对象所有权处理。

2024-05-case Q006

Java 银行账户状态模式与操作委派

阅读下列说明和Java代码,回答问题。
在银行账户管理系统中,账户可以处于多种状态,如激活、冻结、注销等。在每个不同的状态下,都有特定的行为,例如激活状态的账户可以进行存款和取款操作,而冻结状态的账户则不能进行任何操作。现采用State(状态)模式实现上述场景,得到如图1所示的类图。

【Java代码】

interface AccountState {
void deposit(double amount);
void withdraw(double amount);
void freeze();
void unfreeze();
}
class Account {
private (1);
public Account() {
this.state = null;
}
public void setState(AccountState state) {
this.state = state;
}
public void deposit(double amount) {
(2);
}
public void withdraw(double amount) {
(3);
}
public void freeze() {
(4);
}
public void unfreeze() {
(5);
}
}
class ActiveState implements AccountState {
public void deposit(double amount) {
System.out.println("Depositing" + amount + "into the account.");
}
public void withdraw(double amount) {
System.out.println("Withdrawing " + amount + "from the account.");
}
public void freeze() {
System.out.println("Account has been frozen.");
}
public void unfreeze() {
System.out.println("Cannot unfreeze an active account.");
}
}
class FrozenState implements AccountState {
public void deposit(double amount) {
System.out.println("Cannot deposit into a frozen account.");
}
public void freeze() {
System.out.println("Account is already frozen.");
}
public void unfreeze() {
System.out.println("Account has been unfrozen.");
}
}

01(15分)

根据以上说明和Java代码,填充Java代码中的空(1)~(5)。

答案与解析

平台参考答案(原意保留)

平台参考答案:

  1. AccountState state
  2. state.deposit(amount)
  3. state.withdraw(amount)
  4. state.freeze()
  5. state.unfreeze()

解析与纠错

解析与纠错:

  • 五个填空体现状态模式的委派:Account保存AccountState引用,四种操作转交给当前状态。平台填空与现有接口一致。
  • FrozenState 声明实现AccountState,但没有实现 withdraw(double amount),且并非抽象类,因此填完五空后仍不能编译。冻结状态的实现至少还应提供该方法并拒绝取款。
  • Account构造函数把state设为null,立即调用四种委派操作会抛出NullPointerException。可以要求使用前设置有效状态,也可以定义一个明确的初始状态;参考实现约定新账户初始处于激活状态。
  • 原来的 ActiveState.freeze 和 FrozenState.unfreeze 只打印消息,没有调用setState。即使先给账户设置ActiveState,调用freeze后仍然允许执行激活状态的存款逻辑。要产生状态转换,可让具体状态持有Account上下文,在冻结时切换为FrozenState,在解冻时切换为ActiveState。
  • 激活状态的重复解冻和冻结状态的重复冻结可保持原状态并提示;冻结状态拒绝存取款。说明中虽然还提到注销,但给定接口、类图没有提供注销方法和对应状态,不能将其当作五空已有的行为。
  • 参考实现仅用事件记录演示操作和状态转换,没有实现真实余额、金额校验或账务事务。

Java 21 编译和测试通过:有效初始状态、存取款委派、实际冻结/解冻转换、冻结期间拒绝存取款、重复转换、拒绝null状态。

补充与完整参考实现

完整参考实现:

保留原有四种操作,补齐冻结状态的取款方法,并通过上下文实现状态切换。事件列表用于观察状态行为;新账户初始激活是此示例的明确约定。代码文件名为 BankStateDemo.java。

import java.util.ArrayList;
import java.util.List;

interface AccountState {
    void deposit(double amount);
    void withdraw(double amount);
    void freeze();
    void unfreeze();
}

class Account {
    private AccountState state;
    private final List<String> events = new ArrayList<>();
    public Account() { state = new ActiveState(this); }
    public void setState(AccountState state) {
        if (state == null) throw new IllegalArgumentException("state must not be null");
        this.state = state;
    }
    public void deposit(double amount) { state.deposit(amount); }
    public void withdraw(double amount) { state.withdraw(amount); }
    public void freeze() { state.freeze(); }
    public void unfreeze() { state.unfreeze(); }
    void record(String event) { events.add(event); System.out.println(event); }
    public String stateName() { return state.getClass().getSimpleName(); }
    public List<String> events() { return List.copyOf(events); }
}

class ActiveState implements AccountState {
    private final Account account;
    public ActiveState(Account account) { this.account = account; }
    public void deposit(double amount) { account.record("deposit:" + amount); }
    public void withdraw(double amount) { account.record("withdraw:" + amount); }
    public void freeze() {
        account.setState(new FrozenState(account));
        account.record("frozen");
    }
    public void unfreeze() { account.record("already-active"); }
}

class FrozenState implements AccountState {
    private final Account account;
    public FrozenState(Account account) { this.account = account; }
    public void deposit(double amount) { account.record("deposit-rejected:" + amount); }
    public void withdraw(double amount) { account.record("withdraw-rejected:" + amount); }
    public void freeze() { account.record("already-frozen"); }
    public void unfreeze() {
        account.setState(new ActiveState(account));
        account.record("unfrozen");
    }
}

public class BankStateDemo {
    public static void main(String[] args) {
        Account account = new Account();
        account.deposit(100);
        account.freeze();
        account.withdraw(10);
        account.unfreeze();
        account.withdraw(10);
    }
}

2023年下半年软件设计师案例真题(考生回忆版):案例题

本节保留 2 条来源,答案与解析默认收起。

2023-11-case Q003

线上商城的用例、类与多重度

【考生回忆版】

某公司用微信小程序开发线上商城,维护销售商品列表ProductCatalog。商品Product的信息包括商品名称、商品参数、快递费用、商品规格、库存数量。系统功能如下。

  1. 浏览商品:顾客可查看在售商品的详细信息。
  2. 管理收货地址:系统为每位顾客建立AddressBook,可设置1个或多个Address,并选定一个默认地址。顾客可添加、修改、删除地址;地址包含姓名、联系方式、详细地址。
  3. 管理ShoppingCart:顾客可添加、删除、编辑其中的商品,添加时必须选择商品规格和购买数量;购物车允许为空。
  4. 生成Order:顾客可在商品页选择规格和数量后直接生成订单,也可从购物车选择商品生成订单。一个订单可包含多个OrderItem,每个条目对应一个订购商品。
  5. 取消订单:顾客可主动取消未支付订单或已支付但未发货订单;已生成的订单在30分钟内仍未支付,系统自动取消。
  6. 提交订单:必须确定收货地址和付款方式Payment,通常采用默认地址;要换地址,应先修改再提交。付款方式为微信WeChat、支付宝Alpay、数字人民币D-ECN。
  7. 物流追踪:顾客可查询订单状态和物流信息。状态包括待付款、待发货、已完成等;订单处于待收货状态时可查询其物流信息。

面向对象分析得到以下用例图和类图。

图1 用例图

图2 类图

【问题1】(4分)写出图1中U1~U4的用例名称。

【问题2】(9分)

(1)写出图2中C1~C7的类名。

(2)写出图2中M1~M4的多重度。

【问题3】(2分)按需求,类C5和C7至少应包含哪些属性?

答案与解析

平台参考答案(原文保留)

【问题1】

U1:生成订单
U2:提交订单
U3:取消订单
U4:付款方式

【问题2】(类名1分,多重度0.5分)
C1:Order
C2:Address
C3:AddressBook
C4:ProductCatalog
C5:Product
C6:Payment
C7:OrderItem

M1:0..*/*
M2:1..*
M3:1..*
M4:1..*

【问题3】
C5应当包括商品名称、商品参数、快递费用、商品规格、库存数量等。
C7应当包括商品名称、商品数量、订单ID等。

解析与纠错

  1. 按平台映射,U1生成订单、U2提交订单、U3取消订单,U4付款方式。U2与U4之间的include线,以及微信/支付宝/数字人民币支付指向U4的泛化线,说明U4处在支付相关行为的位置;用例通常以“支付”等动作命名,“付款方式”是平台保留用词。
  2. 类名依次是C1 Order、C2 Address、C3 AddressBook、C4 ProductCatalog、C5 Product、C6 Payment、C7 OrderItem。C1端实心菱形表示订单组合订单条目;C3和C4端的空心菱形分别对应地址列表和商品列表;三种支付实现泛化到C6。
  3. M1位于购物车对应的商品端,购物车可空,因此是0..;M2为一个订单包含的条目数,按有效订单至少有一条购买项取1..;M3由每份地址列表可设1个或多个地址,取1..。M4平台填1..,但“维护商品列表”本身并不推出目录永远非空;若允许尚未上架或全部下架,0..*也合理。保留平台M4并说明其需要非空目录的额外假设。
  4. C5的属性由说明直接取得:商品名称、商品参数、快递费用、商品规格、库存数量。C7需要表达购买数量,以及关联的商品和所属订单;所选规格也必须能被确定,可通过条目属性或所关联的具体商品规格对象表达。平台给出的“商品名称、商品数量、订单ID”保留,但在类模型中,商品/订单关联可以承担标识关系,不一定必须把名称和订单ID都重复存成独立属性。

图示局限:C5与C7连线两端都印有1,实际上限制了一个商品只对应一个订单条目,不能表达同一商品出现在多个订单中的常见情况;ShoppingCart端的1也限制每个Product实例只属一个购物车。这里保留原图,不通过改M1~M4掩盖这些已印出的约束。U2、U3以extend指向U1,并不表示“先生成再提交/取消”的时间先后;include也表示被包含行为必然执行,而非仅有付款方式字段。平台以业务先后解释extend不严谨。正文WeChat、Alpay、D-ECN与图中的WeChatPay、Alipay、D·ECN拼写不同,按各来源保留。

2023-11-case Q005

公告栏系统的命令模式填空

【考生回忆版】

某公司开发公告栏系统,通过菜单执行创建、打开、编辑公告栏等操作。系统采用Command(命令)模式,类图如下。

图1 命令模式类图

【Java代码】

import java util*;  
(1) class Command {  
(2);  
public (3);  
}  
class createCommand extends Command {  
public createCommand() { bs = new BoardScreen();}  
public void execute() { bs.create();}  
}  
class openCommand extends Command (  
public openCommand() ( bs = new BoardScreen();)  
public void execute()( bs.open();)

}

class openCommand extends Command (  
public openCommand() ( bs = new BoardScreen();)  
public void execute()( bs.edit();)

}

class BoardScreen{  
public void open() ( System. out println("open BoardScreen'), )  
public void create() {System.out.println("create BoardScree").}  
public void edit() {System.out.println("edit BoardScree");}

}

class Menultem {  
private Command command;  
private String itemName;  
public Menultem(Command command, String itemName) {  
this.command = command;  
this.itemName = itemName;  
}  
public String getltemName(){return itemName;}  
public void click(){  
System.out.println("Menultem "+ this.itemName + " is excuting);  
(4)

}

}

class Menu {  
private ArrayList < Menultem > MenultemsList = new ArrayList < Menultem > 0;  
public void addMenultem(Menultem item) ( MenultemsList.add(item);)  
public void runMenultem(String itemName) {  
for (int i= 0; i < MenultemsList.size(), i+ +) {  
if(MenulternsList get(i)getItemName().equals (itemName)) {  
MenultemsList.get(i).(5);  
return;

}

}

}

}

根据说明和Java代码,填写(1)~(5)。

答案与解析

平台参考答案(原文保留)

1、public abstract
2、BoardScreen bs;
3、abstract void execute();
4、command.execute();
5、click()

解析与纠错

五处填空的职责与平台答案一致:

  1. public abstract:Command包含抽象操作,必须为抽象类;public是平台采用的可见性。
  2. BoardScreen bs:保存实际执行公告栏操作的接收者,具体命令构造器为它赋值。
  3. abstract void execute():定义统一操作;题干在该空前已有public。
  4. command.execute();:菜单项作为调用者,点击时委托给其持有的命令。
  5. click():菜单按名称找到菜单项后,触发该项的点击操作。

题干在(2)、(3)后已给分号,填写时可不再写;平台答案多带一个分号形成类体空声明,并非本题主要错误。创建、打开、编辑命令分别把execute转交给BoardScreen的create、open、edit,因此新增操作时可新增具体命令,而不在菜单项里集中判断每种业务操作。

原站可见页面已核实:两个实现类及其构造器均名为openCommand,第二个却调用bs.edit;图中另有editCommand。import java util*;、方法体括号混用、println前缺点、单双引号不配对、create语句结尾为.}、click的is excuting字符串未闭合、ArrayList构造以字符0结尾、if表达式中的拼写与成员访问符号错误,均为原题问题。Menu类结束后直接进入填空说明,未漏后续代码;全部五空可见。getItemName的I/l字形无法仅凭截图完全区分,上方保留原题代码的写法。五空填全后原片段仍不能编译。

补充说明

整理修正时,应将导入改为import java.util.*;,第二个openCommand及其构造器改为editCommand,并修复花括号、点、分号、字符串引号和new ArrayList<...>()。菜单项类、列表变量及访问方法须统一拼写,方法统一为getItemName(),再使用列表的get(i)取得菜单项并比较其名称。这些是依据类图和Java语法作出的整理修正,不是原页代码;不改动上方原题片段或平台答案。

2023年下半年软件设计师考试基础知识(专业解析+参考答案)

本节已整理 13 条来源记录;题号沿用来源,答案与解析默认收起。

2023-11 Q006

来源:第 6 题(原站入口)。

【考生回忆版】在下面的UNL用例图中,A1与A2表示( 6 )。已知UC4为抽象用例,则A2可与系统交互的用例为( 7 )。

请作答:第6题。

  • A.

    外部软件

  • B.

    人

  • C.

    参与者

  • D.

    系统

答案与解析

平台答案:C。

整理解析

选C。用例图的人形符号表示参与者,即在系统边界之外与系统交互的角色。参与者可以由人、外部软件或设备承担,不能仅凭人形画法把它限制为“人”。

补充与纠错

题干的“UNL”按原文保留,此处术语应为UML。参与者表示角色,不必是某个具体人或一台固定机器。

2023-11 Q007

来源:第 7 题(原站入口)。

【考生回忆版】在下面的UNL用例图中,A1与A2表示( 6 )。已知UC4为抽象用例,则A2可与系统交互的用例为( 7 )。

请作答:第7题。

  • A.

    只有UC1

  • B.

    UC1和UC4

  • C.

    只有UC4

  • D.

    UC1和UC5

答案与解析

平台答案:D。

整理解析

选D。A2泛化到A1,因而可继承A1与UC1的交互关系。A2还关联抽象用例UC4,图中UC1与UC5是UC4的具体特化,因此按图意可交互的具体用例为UC1和UC5,不直接执行抽象的UC4。

补充与纠错

用例的泛化表达行为规格的特化,不能照平台解析把它说成“通过子类访问抽象用例内部方法”。此处依据图中泛化与关联关系解释可参与的具体用例,原题UNL字样仍保留。

2023-11 Q008

来源:第 8 题(原站入口)。

【考生回忆版】某软件界面提供浅色和深色两种主题,用户可自行选择、切换。为实现这一需求,设计下列类图。该设计采用( 8 )模式,适用情形为( 9 )。

请作答:第8题。

  • A.

    原型(Prototype)

  • B.

    抽象工厂(Abstract Factory)

  • C.

    工厂方法(Factory Method)

  • D.

    生成器(Builder)

答案与解析

平台答案:B。

整理解析

选B。图中LightTheme与DarkTheme分别对应浅色和深色产品族,每族都包含Toolbar与Dialog两类界面对象,客户端面向Theme及产品接口使用它们。创建一整族相互配套的产品,符合抽象工厂模式的意图。

补充与纠错

仅有主题切换需求并不必然要求抽象工厂,还应结合图中Toolbar/Dialog成组的产品族设计。该模式便于增加一套主题产品,但新增产品种类常需扩展工厂接口;也不自动保证已创建组件的实时换肤。

2023-11 Q009

来源:第 9 题(原站入口)。

【考生回忆版】某软件界面提供浅色和深色两种主题,用户可自行选择、切换。为实现这一需求,设计下列类图。该设计采用( 8 )模式,适用情形为( 9 )。

请作答:第9题。

  • A.

    当一个类希望由它的子类来指定它所创建的对象时

  • B.

    一个系统要由多个产品系列中的一个来配置时

  • C.

    为了避免创建一个与产品类层次平行的工厂类层次时

  • D.

    当构造过程必须允许被构造的对象有不同的表示时

答案与解析

平台答案:B。

整理解析

选B。系统在浅色、深色两个产品族中选择一族来配置,Toolbar与Dialog要保持同一主题,因此适合抽象工厂。A描述工厂方法的子类决定创建对象,C对应原型的典型动机,D强调生成器把构造过程与表示分离。

2023-11 Q010

来源:第 10 题(原站入口)。

【考生回忆版】活动图用于建模( 10 )。对下面的活动图,不可能的活动顺序为( 11 )。

请作答:第10题。

  • A.

    系统内构件之间的组织和依赖

  • B.

    系统内从一个活动到另一个活动的流程

  • C.

    一组对象、接口、协作和它们之间的关系

  • D.

    以时间顺序组织的对象之间的交互活动

答案与解析

平台答案:B。

整理解析

选B。活动图描述活动及其间控制流或数据流,适合表示从一个活动推进到另一个活动的过程。A对应构件组织与依赖,D对应按时间顺序组织的交互;本图的动作、分支和并发控制都支持B。

补充与纠错

C的原文为“一组对象、接口、协作和它们之间的关系”,不应直接照平台称为标准类图定义;类图通常描述的是类、接口、协作及关系。原选项不改,本题B仍明确。图中起点画成空心圆也不规范,但不影响本问活动图用途的判断。空11保留,未将后续小问答案写进题干。

2023-11 Q011

来源:第 11 题(原站入口)。

【考生回忆版】活动图用于建模( 10 )。对下面的活动图,不可能的活动顺序为( 11 )。

请作答:第11题。

  • A.

    Act1 → Act2 → Act6

  • B.

    Act1 → Act6

  • C.

    Act1→ Act2→ Act3→ Act4 →Act6

  • D.

    Act1→ Act2→ Act5→ Act6

答案与解析

平台答案:A。

整理解析

平台选A:Act2之后没有绕过中间动作直接进入Act6的控制流。若把选项理解为沿图上单条路径列出的动作,B走外侧分支,C和D分别走并发结构的一侧,能解释平台的判题意图。

补充与纠错

原页已核实:原题没有“图上一条路径/局部序列”的额外约定,图中确为并发分岔/汇合。黑色粗条不是二选一:一旦执行Act2,Act5与Act3→Act4两支都要完成,才能进入Act6。若“活动顺序”指包含全部动作的完整执行序列,C和D也各漏掉一支,A并非唯一不成立项。平台把两支当作任选其一的完整运行路径不严谨;保留平台A,不将这种解释写成UML规则。

2023-11 Q014

来源:第 14 题(原站入口)。

【考生回忆版】用面向对象方法开发学生成绩管理系统。学生姓名、性别、出生日期、期末考试成绩及查看成绩操作一起被( 14 )在学生对象中。系统定义了不同的类,这些类的对象之间通过( 15 )通信。

请作答:第14题。

  • A.

    继承

  • B.

    封装

  • C.

    信息

  • D.

    多态

答案与解析

平台答案:B。

整理解析

选B。把学生的数据及查看成绩的操作组织到同一对象,并通过其接口访问,是封装。继承描述类型层次中的特征继承,不等于把一组属性和操作放在一起。

补充与纠错

平台将继承说成“一个对象直接使用另一对象的属性和方法”不准确:一般对象间的调用不等于继承,继承应结合类或类型的派生关系理解。

2023-11 Q015

来源:第 15 题(原站入口)。

【考生回忆版】用面向对象方法开发学生成绩管理系统。学生姓名、性别、出生日期、期末考试成绩及查看成绩操作一起被( 14 )在学生对象中。系统定义了不同的类,这些类的对象之间通过( 15 )通信。

请作答:第15题。

  • A.

    重载

  • B.

    消息

  • C.

    多态

  • D.

    继承

答案与解析

平台答案:B。

整理解析

选B。对象向另一对象发送消息,请求它执行相应行为;常见语言中表现为方法调用。重载、多态、继承描述不同的语言机制,并不是这里所问的对象通信方式。

2023-11 Q018

来源:第 18 题(原站入口)。

【考生回忆版】某通关游戏要求玩家可保存当前进度和状态,并在游戏过程中回退到先前保存的状态。玩家属性包括库存、分数、级别和位置。为此设计了下列类图。该设计采用( 18 )模式,由( 19 )存储玩家的内部状态。

请作答:第18题。

  • A.

    选代器(Iterator)

  • B.

    观察者(Observer)

  • C.

    备忘(Memento)

  • D.

    中介者(Mediator)

答案与解析

平台答案:C。

整理解析

选C。需求的关键是保存对象某一时刻的状态,并在之后恢复。图中的GameCharacter对应原发器,CharacterState保存状态快照,CareTaker管理保存和恢复,符合备忘录模式。

补充与纠错

A项原文“选代器”保留,Iterator的通常译名是“迭代器”。题图是角色示意,备忘录的封装边界仍需实现保证,不能仅由图中属性列出就推断实现已做到完全封装。

2023-11 Q019

来源:第 19 题(原站入口)。

【考生回忆版】某通关游戏要求玩家可保存当前进度和状态,并在游戏过程中回退到先前保存的状态。玩家属性包括库存、分数、级别和位置。为此设计了下列类图。该设计采用( 18 )模式,由( 19 )存储玩家的内部状态。

请作答:第19题。

  • A.

    CharacterState

  • B.

    GameCharacter

  • C.

    CareTaker

  • D.

    Client

答案与解析

平台答案:A。

整理解析

选A。CharacterState中列有score、inventory、level、location,承担保存玩家状态快照的职责。GameCharacter是当前游戏角色,CareTaker保管快照并协调保存/恢复,Client是使用者。

2023-11 Q023

来源:第 23 题(原站入口)。

【考生回忆版】对采用面向对象方法开发的系统分层测试,其中测试类中定义的每个方法,属于( )层。

  • A.

    系统

  • B.

    算法

  • C.

    类

  • D.

    模板

答案与解析

平台答案:B。

同题对照:标准题。来源选项→标准题选项:A→B,B→D,C→C,D→A。

映射后平台答案:D。

重复判断依据

两题均问面向对象测试中逐一测试类内方法属于哪个层次;系统、算法、类、模板四项相同,仅重排。目标卷的单元测试类比不增加不同作答条件。

2023-11 Q029

来源:第 29 题(原站入口)。

【考生回忆版】关于方法重载(Overload)、方法覆盖(Overide)与多态,下列说法不正确的是( )。

  • A.

    覆盖通过动态绑定机制实现多态

  • B.

    重载通过动态绑定机制实现多态

  • C.

    重载属于编译时多态,在一个类中定义多个名称相同而参数表不同的方法

  • D.

    覆盖属于运行时多态,子类重新定义父类中已定义的方法

答案与解析

平台答案:B。

整理解析

选B。在题目采用的常见静态类型语言模型下,重载依据编译时已知的参数表选择方法,属于编译时多态;覆盖可依据运行时对象类型动态分派。动态绑定不是重载本身的选择机制。

补充与纠错

保留原题Overide拼写,通常写作Override/Overriding。子类出现同名方法不自动构成覆盖,还要满足方法签名及语言对可覆盖方法的规则;静态方法等也不一定参与动态分派。

2023-11 Q045

来源:第 45 题(原站入口)。

若要在不修改对象结构的前提下,动态为对象增加职责,应采用哪一种设计模式?

  • A.

    装饰(Decorator)

  • B.

    外观(Facade)

  • C.

    组合(Composite)

  • D.

    享元(Flyweight)

答案与解析

平台答案:A。

同题对照:标准题。来源选项→标准题选项:A→D,B→B,C→A,D→C。

映射后平台答案:D。

重复判断依据

两题均问不改变对象结构、动态增加职责的模式;对应知识题第一空42,后两空是独立定义,并不添加该空条件。四种模式相同,装饰与装饰器均明确标注Decorator。

2023年上半年软件设计师应用技术:案例题

本节保留 3 组案例。

2023-05-case Q003

数字图书馆的对象模型

阅读下列说明和图,回答问题1至问题3,将解答填入答题纸的对应栏内。

【说明】

某高校图书馆购买了若干学术资源的镜像数据库(MirrorDB)资源,现要求开发一套数字图书馆 (Digital Library) 系统,面向校内用户 (User) 提供学术资源 (Resource) 的浏览、检索和下载服务,系统的主要要求描述如下:
(1)系统中存储了每个镜像数据库的基本信息,包括:数据库名称、访问地址、数据库属性以及数据库简介等信息,用户进入某个镜像数据库后,可以浏览、检索以及下载其中的学术资源。

(2)学术资源包括会议论文(Conference Paper)、期刊论文(Journal Article)以及学位论文(Thesis)等。系统中存储了每个学术资源的题名、作者、发表时间、来源(哪个镜像数据库)、被引次数、下载次数等信息。对于会议论文,还需记录会议名称、召开时间以及召开地点;同一次会议的论文被收录在会议集(Proceeding)中。对于期刊论文,还需记录期刊名称、出版月份、期号以及主办单位;同一期号的论文被收录在一本期刊(Edition)中。对于学位论文,记录了学位类别 (博士/硕士)、毕业学校、专业以及指导教师。
会议集包含发表在该会议 (在某个特定时间段、特定地点召开) 上的所有文章。期刊的每一期在特定时间发行,其中包含若干篇文章。
(3)系统用户 (User) 包括在校学生 (Student)、教师 (Teacher) 以及其他在职人员 (Staff) 。用户使用学校的统一身份认证登录系统后,使用系统提供的各项服务。
(4)系统提供多种资源检索的方式,主要包括:按照资源的题名检索 (Search By Title) 、按照作者名称检索 (Search By Author) 、按照来源检索 (Search By Source) 等。
(5)用户可以下载资源,系统记录每个资源被下载的次数。

现采用面向对象分析与设计方法开发该系统,得到如图3-1所示的用例图以及图3-2所示的初始类图。

【问题1】(8分)

根据说明中的描述,给出图3-2中的C1~C8所对应的类名。
【问题2】(4分)

根据说明中的描述,给出图3-2中的类C1~C4的关键属性。
【问题3】(3分)

在该系统的开发过程中遇到了新的要求:用户能够在系统中对其所关注的数字资源注册他引通知,若该资源的他引次数发生变化,系统可以及时通知该用户。为了实现这个新的要求,可以在图3-2所示的类图中增加哪种设计模式?用150字以内文字解释选择该模式的原因。

答案与解析

平台参考答案(原意保留)

【问题1】

C1:Resource C2:ConferencePaper C3:JournalArticle C4:Thesis C5:User C6--C8不限顺序 C6:Student C7:Teacher C8:Staff

【问题2】

C1: 题名、作者、发表时间、来源、被引次数、下载次数

C2: 会议名称、召开时间、召开地点

C3: 期刊名称、出版月份、期号、主办单位

C4: 学位类别、毕业学校、专业、指导教师

【问题3】

观察者模式
观察者模式定义对象间的一对多的关系,当一个对象的状态发生改变、所有依赖于它的对象都将得到通知并自动更新。符合系统需求。

解析与纠错

类名。 C1是Resource;C2连向Proceeding,故是ConferencePaper;C3连向Edition,故是JournalArticle;C4是Thesis。C5是User,其三个子类C6、C7、C8可分别为Student、Teacher、Staff,三者排列可互换。判断依据是泛化箭头朝向父类,以及各类和会议集、期刊的关联位置,而不是类框编号的先后。

关键属性。 Resource集中保存题名、作者、发表时间、来源、被引次数、下载次数,子类继承这些属性。ConferencePaper另有会议名称、召开时间、召开地点;JournalArticle另有期刊名称、出版月份、期号、主办单位;Thesis另有学位类别、毕业学校、专业、指导教师。来源可以实现为指向MirrorDB的关联,不必同时存一份可能不一致的数据库名称。

通知需求(150字以内示例)。 采用观察者模式。将资源作为被观察对象,关注该资源的用户或通知服务作为观察者,支持订阅和取消订阅。当资源他引次数变化时,通知已注册观察者。资源无须依赖各用户的具体通知方式,新增通知渠道也不必修改资源更新逻辑。

图例纠错。 图3-2中Proceeding、Edition端画的是空心菱形,表示聚合;平台解析称之为“组合关系”不准确,组合通常使用实心菱形。空心菱形不承诺论文与容器具有不可分离的生命周期。新需求说“他引次数”,而已有属性说“被引次数”;若业务区分他引与自引,应明确新增统计口径和触发字段,不能把所有被引变化都自动当作他引变化。

2023-05-case Q005

区间显示程序(Java)

阅读下列说明和Java代码,将应填入 (n) 处的字句写在答题纸的对应栏内。
【说明】
在某系统中,类Interval代表由下界(lower bound)和上界 (upper bound) 定义的区间,要求采用不同的格式显示区间范围,如[lower bound,upper bound]、[lower bound…upper bound]、[lower bound - upper bound]等。现采用策略 (strategy) 模式实现该要求,得到如图5-1所示的类图。

【Java代码】

import java.util.*;

enum TYPE { COMMA, DOTS, LINE};

interface PrintStrategy {
public (1);

}

class Interval {
private double lowerBound;
private double upperBound;
public Interval(double p_lower, double p_upper) {
lowerBound = p_lower; upperBound = p_upper;

}
public void printInterval( PrintStrategy ptr ) {
(2);

}
public double getLower() { retun lowerBound; }
public double getUpper() { return upperBound; }

}

class PrintIntervalsComma implements PrintStrategy {
public void doPrint(Interval val) {
System.out.println("[" + val.getLower() + "," + val.getUpper() + "]");

}

}

class PrintIntervalsDots implements PrintStrategy{
public void doPrint(Interval val) {
System.out.println("[" + val.getLower() +"…" + val.getUpper() + "]");

}

}

class PrintIntervalsLine implements PrintStrategy {
public void doPrint(Interval val) {
System.out.println("[" + val.getLower() +"-" + val.getUpper() + "]");

}

}

class Strategy{
public static PrintStrategy getStrategy(TYPE type) {
PrintStrategy st = null;
switch(type) {
case COMMA:
(3);
break;
case DOTS:
(4);
break;
case LINE:
(5);
break;

}
return st;

}

public static void main(String[] args) {
Interval a = new Interval(1.7,2.1);
a.printInterval(getStrategy(TYPE.COMMA));
a.printInterval(getStrategy(TYPE.DOTS));
a.printInterval(getStrategy(TYPE.LINE));

}

}
答案与解析

平台参考答案(原意保留)

(1)void doPrint(Interval val);

(2)ptr.doPrint(this)

(3)st=new Printintervalscomma()

(4)st=new PrintIntervalsDots()

(5)st=new PrintIntervalsLine()

解析与纠错

填空。 (1)void doPrint(Interval val);(2)ptr.doPrint(this);(3)st = new PrintIntervalsComma();(4)st = new PrintIntervalsDots();(5)st = new PrintIntervalsLine()。原空位之后已经有分号。平台(1)末尾再给一个分号属于冗余,Java接口允许空声明,主要错误不是这个多余分号。

策略委派。 Interval把自身传给PrintStrategy接口的方法,各具体策略读取相同上下界,决定用逗号、省略号还是连字符连接。改变策略即可改变显示格式,无须在Interval内部针对每种输出格式增加分支。getStrategy承担策略对象的创建和选择。

代码纠错。 原页已确认:题干getLower写成retun lowerBound,需改为return lowerBound;平台(3)的Printintervalscomma与已声明的PrintIntervalsComma大小写不一致,会导致类无法解析。可见题干和平台答案保留这些原始拼写,完整参考实现另行给出。

本题Java省略号策略实际输出单个字符…,与C++题的三个句点...不同,不能在原代码中默默统一。图把Interval与策略画为组合,但代码只通过方法参数临时使用策略,没有存储或拥有它;严格的代码对应关系更接近依赖,若要求体现组合应另设计持有和生命周期管理。

Java21验证了原例三种精确输出、负数与零、相等和反向上下界、自定义策略的调用次数与接收对象,以及空策略和空类型的拒绝。题干未定义区间合法性规则,示例仅负责格式化,不擅自交换反向上下界。

补充与完整参考实现

以下为按题意编写并验证的修正示例,包含填空之外的修正与边界处理。

import java.util.Objects;

enum TYPE { COMMA, DOTS, LINE }
interface PrintStrategy {
    void doPrint(Interval val);
}
class Interval {
    private final double lowerBound;
    private final double upperBound;
    public Interval(double lower, double upper) {
        lowerBound = lower;
        upperBound = upper;
    }
    public void printInterval(PrintStrategy ptr) {
        Objects.requireNonNull(ptr, "strategy").doPrint(this);
    }
    public double getLower() { return lowerBound; }
    public double getUpper() { return upperBound; }
}
class PrintIntervalsComma implements PrintStrategy {
    public void doPrint(Interval val) {
        System.out.println("[" + val.getLower() + "," + val.getUpper() + "]");
    }
}
class PrintIntervalsDots implements PrintStrategy {
    public void doPrint(Interval val) {
        System.out.println("[" + val.getLower() + "…" + val.getUpper() + "]");
    }
}
class PrintIntervalsLine implements PrintStrategy {
    public void doPrint(Interval val) {
        System.out.println("[" + val.getLower() + "-" + val.getUpper() + "]");
    }
}
public class Strategy {
    public static PrintStrategy getStrategy(TYPE type) {
        return switch (Objects.requireNonNull(type, "type")) {
            case COMMA -> new PrintIntervalsComma();
            case DOTS -> new PrintIntervalsDots();
            case LINE -> new PrintIntervalsLine();
        };
    }
    public static void main(String[] args) {
        Interval a = new Interval(1.7, 2.1);
        for (TYPE type : TYPE.values()) a.printInterval(getStrategy(type));
    }
}

2023-05-case Q006

区间显示程序(C++)

阅读下列说明和C++代码,将应填入 (n) 处的字句写在答题纸的对应栏内。
【说明】
在某系统中,类Interval代表由下界(lower bound)和上界 (upper bound) 定义的区间,要求采用不同的格式显示区间范围,如[lower bound,upper bound]、[lower bound...upper bound]、[lower bound - upper bound]等。现采用策略 (Strategy) 模式实现该要求,得到如图6-1所示的类图。

【c++代码】

#include < iostream >
using namespace std;

class Interval;
class PrintStrategy {
public:
(1);
};
class Interval {
private:
double lowerBound;
double upperBound;

public:
Interval(double p_lower, double p_upper) {
lowerBound = p_lower;
upperBound = p_upper;

}
void printInterval(PrintStrategy*ptr){
(2);

}
double getLower() { return lowerBound; }
double getUpper() { return upperBound; }

};

class PrintIntervalsComma: public PrintStrategy {
public:
void doPrint(Interval *val) {
cout < < "[" < < val- > getLower() < < "," < < val- > getUpper() < < "]" < < endl; }

};

class PrintIntervalsDots: public PrintStrategy {
public:
void doPrint(Interval *val) {

cout < < "[" < < val- > getLower() < < "..." < < val- > getUpper() < < "]" < < endl; }

};

class PrintIntervalsLine:public PrintStrategy {
public:
void doPrint(Interval *val) {
cout < < "[" < < val- > getLower() < < "-" < < val- > getUpper() < < "]" < < endl; }

};

enum TYPE {COMMA, DOTS, LINE};
PrintStrategy* getStrategy(int type) {
PrintStrategy* st;
switch(type){
case COMMA:
(3);
break;
case DOTS:
(4);
break;
case LINE:
(5);
break;

}
return st;

}

int main() {
Interval a(1.7,2.1);
a.printInterval(getStrategy(COMMA));
a.printInterval(getStrategy(DOTS));
a.printInterval(getStrategy(LINE));
return 0;

}
答案与解析

平台参考答案(原意保留)

(1)virtual void doprint(Interval *val)=0

(2)ptr- > doPrint(this)

(3)st=new PrintIntervalsComma()

(4)st=new PrintIntervalsDots()

(5)st=new PrintIntervalsLine()

解析与纠错

填空。 (1)virtual void doPrint(Interval *val) = 0;(2)ptr->doPrint(this);(3)st = new PrintIntervalsComma();(4)st = new PrintIntervalsDots();(5)st = new PrintIntervalsLine()。纯虚函数为各格式类建立统一接口,Interval通过基类指针调用它,运行时选择相应的具体实现。

大小写错误。 原页已确认:平台(1)写成doprint,但调用与三个派生类实现均为doPrint。C++区分大小写,这会同时造成基类没有被调用的方法,以及派生类未实现纯虚函数、仍为抽象类。必须统一成doPrint,仅照抄平台答案不能通过编译。

其他源码问题。 题干代码中分开的< <、- >、头文件两侧空格和类末尾全角;需要按C++词法修正。工厂原来的局部指针st没有初始化,遇到未知type会返回不确定值;对三个合法枚举值则会被相应分支赋值。原main三次new没有对应delete。补充实现使用unique_ptr管理策略、为基类增加虚析构函数,并拒绝未知类型和空策略指针。这些是修正示例的增强,不是原题隐含空号。

与Java版本一样,原代码通过参数临时借用策略,未体现类图实心菱形所表达的组合所有权。此处仍保持方法委派结构,由调用方持有策略对象,不声称已经实现图中的组合关系。

C++17验证了原例三种精确输出、负数与零、相等和反向上下界、自定义策略的调用对象与次数、空指针与非法type拒绝,以及经基类指针释放时派生类析构确实发生。

补充与完整参考实现

以下为按题意编写并验证的修正示例,包含填空之外的修正与边界处理。

#include <iostream>
#include <memory>
#include <stdexcept>

class Interval;
class PrintStrategy {
public:
    virtual ~PrintStrategy() = default;
    virtual void doPrint(Interval *val) = 0;
};
class Interval {
    double lowerBound, upperBound;
public:
    Interval(double lower, double upper) : lowerBound(lower), upperBound(upper) {}
    void printInterval(PrintStrategy *ptr) {
        if (!ptr) throw std::invalid_argument("null strategy");
        ptr->doPrint(this);
    }
    double getLower() const { return lowerBound; }
    double getUpper() const { return upperBound; }
};
class PrintIntervalsComma : public PrintStrategy {
public:
    void doPrint(Interval *val) override {
        std::cout << '[' << val->getLower() << ',' << val->getUpper() << "]\n";
    }
};
class PrintIntervalsDots : public PrintStrategy {
public:
    void doPrint(Interval *val) override {
        std::cout << '[' << val->getLower() << "..." << val->getUpper() << "]\n";
    }
};
class PrintIntervalsLine : public PrintStrategy {
public:
    void doPrint(Interval *val) override {
        std::cout << '[' << val->getLower() << '-' << val->getUpper() << "]\n";
    }
};
enum TYPE { COMMA, DOTS, LINE };
std::unique_ptr<PrintStrategy> getStrategy(int type) {
    switch (type) {
        case COMMA: return std::make_unique<PrintIntervalsComma>();
        case DOTS: return std::make_unique<PrintIntervalsDots>();
        case LINE: return std::make_unique<PrintIntervalsLine>();
        default: throw std::invalid_argument("unknown strategy type");
    }
}
#ifndef STRATEGY_NO_MAIN
int main() {
    Interval a(1.7, 2.1);
    for (int type : {COMMA, DOTS, LINE}) {
        auto strategy = getStrategy(type);
        a.printInterval(strategy.get());
    }
}
#endif

2023年上半年软件设计师考试基础知识(专业解析+参考答案)

本节已整理 11 条来源记录;题号沿用来源,答案与解析默认收起。

2023-05 Q037

来源:第 37 题(原站入口)。

用面向对象方法开发学生成绩管理系统。学生的姓名、性别、出生日期、期末考试成绩和查看成绩操作被( 37 )在学生对象中。系统定义不同类,各类的对象之间通过( 38 )通信。

请作答:第37题。

  • A.

    封装

  • B.

    继承

  • C.

    多态

  • D.

    信息

答案与解析

平台答案:A。

同题对照:标准题。来源选项→标准题选项:A→B,B→A,C→D,D→C。

映射后平台答案:B。

重复判断依据

同一学生成绩管理场景:姓名、性别、出生日期、期末成绩及查看成绩操作纳入学生对象;本问均识别这种组织机制,源空37对应目标空14,另一通信空分别为38/15。

补充与纠错

完整学生材料及通信小问第38空都保留;本问只识别数据与操作的组织方式,不把下一问的通信答案填入题干。

2023-05 Q038

来源:第 38 题(原站入口)。

用面向对象方法开发学生成绩管理系统。学生的姓名、性别、出生日期、期末考试成绩和查看成绩操作被( 37 )在学生对象中。系统定义不同类,各类的对象之间通过( 38 )通信。

请作答:第38题。

  • A.

    继承

  • B.

    多态

  • C.

    消息

  • D.

    重载

答案与解析

平台答案:C。

同题对照:标准题。来源选项→标准题选项:A→D,B→C,C→B,D→A。

映射后平台答案:B。

重复判断依据

同一学生成绩管理场景;本问均问不同类的对象之间通过什么通信,源空38对应目标空15,不能与组织机制的37/14空混并。

补充与纠错

发送消息不必指跨网络通信,也不要求所有语言都使用异步消息队列;在此是对象请求对方执行行为的概念。第37空保持未填。

2023-05 Q039

来源:第 39 题(原站入口)。

采用面向对象方法开发的系统可在不同层次测试。测试类中定义的每个方法,属于( )层。

  • A.

    算法

  • B.

    类

  • C.

    模板

  • D.

    系统

答案与解析

平台答案:A。

同题对照:标准题。来源选项→标准题选项:A→D,B→C,C→A,D→B。

映射后平台答案:D。

重复判断依据

都问面向对象分层测试中逐一测试类中方法所属层次;算法、类、模板、系统四项相同,仅换序。选择直接标准题2024春20,避免经过2023秋23的别名链。

2023-05 Q040

来源:第 40 题(原站入口)。

面向对象系统设计中,若重用一个包中的某个类,就要重用该包中所有类,这对应( )原则。

  • A.

    共同封闭

  • B.

    共同重用

  • C.

    开放封闭

  • D.

    接口分离

答案与解析

平台答案:B。

同题对照:标准题。来源选项→标准题选项:A→C,B→D,C→B,D→A。

映射后平台答案:D。

重复判断依据

题干均为重用包中一个类就需重用包中所有类,四个原则相同;开放封闭与开放-封闭只是连接符差别。

补充与纠错

这条原则不要求运行时显式调用或实例化包中每一个类;它约束包的职责和依赖。平台“把所有要引用的第三方类封装到一个包”不是普遍可取的做法,也不是该原则的定义。

2023-05 Q041

来源:第 41 题(原站入口)。

下图所示的 UML 图主要展现(41);图中可能出现的消息序列是(42)。

请作答:第41题。

  • A.

    系统在它的周边环境的语境中所提供的外部可见服务

  • B.

    某一时刻一组对象以及它们之间的关系

  • C.

    系统内从一个活动到另一个活动的流程

  • D.

    以时间顺序组织的对象之间的交互活动

答案与解析

平台答案:D。

整理解析

图中对象沿横向排列,纵向生命线和消息箭头呈现交互的时间顺序,是顺序图(序列图),对应D。它的重点是对象如何发送、接收消息,而非静态对象快照或活动流程。

2023-05 Q042

来源:第 42 题(原站入口)。

下图所示的 UML 图主要展现(41);图中可能出现的消息序列是(42)。

请作答:第42题。

  • A.

    a→b→c→a→b

  • B.

    c

  • C.

    a→b→a→b→c

  • D.

    a→b→c→a→b→c

答案与解析

平台答案:C。

整理解析

图中 loop(1..2) 框只包住消息a、b,表示这段至少执行一次、至多两次;消息c位于框外,在循环结束后发送。因此完整消息序列可为abc或ababc,四个选项中只有C的a→b→a→b→c符合。

2023-05 Q043

来源:第 43 题(原站入口)。

UML包图描述模型分解出的组织单元及其依赖关系。以下关于包图的说法,哪一项不正确?

  • A.

    可以拥有类、接口构件、节点

  • B.

    一个元素可以被多个包拥有

  • C.

    一个包可以嵌套其他包

  • D.

    一个包内元素不能重名

答案与解析

平台答案:B。

整理解析

模型元素的拥有者不能同时是多个包;元素可以被别的包引用或导入,但这不等于被多个包共同拥有,因此选B。包可以包含类、接口等可打包元素,也可以嵌套其他包。

补充与纠错

概念边界:平台用Java子包举例并不严谨,Java的a.b并非自动拥有a包的访问权限,不能把Java名称层次直接等同于UML的拥有关系。D是常见命名要求的简化,精确规则应按UML命名空间中成员的可区分性解释。

2023-05 Q044

来源:第 44 题(原站入口)。

招聘系统需要自动生成简历,内容包含求职者姓名、性别、年龄和工作经历等;不同简历的工作经历希望有所不同,同时尽量减少重复代码。按下图设计,采用(44)模式,声明复制自身的接口。原题另写“由xx实例指定创建对象的种类”“通过复制这些Resume xx WorkExperience的对象来创建新的对象”。该模式属于(45)模式。

请作答:第44题。

  • A.

    单例(Singleton)

  • B.

    抽象工厂(Abstract Factory)

  • C.

    生成器(Builder)

  • D.

    原型(Prototype)

答案与解析

平台答案:D。

整理解析

通过已有实例的复制接口创建新实例,是原型模式的识别条件,选D。图中Resume和WorkExperience都具备来自上层cloneable的复制能力。

补充与纠错

原页已核实:题面两处xx确为原网页文字,均保留原样,不猜补缺词。图中Resume端标1、WorkExperience端标1..*,空心菱形位于Resume端,表示聚合关系。若简历的可变工作经历要各自独立修改,复制时还需处理被引用对象,不能以为原型模式天然保证深复制;“只有原型模式能减少重复代码”也不是通用结论。

2023-05 Q045

来源:第 45 题(原站入口)。

招聘系统需要自动生成简历,内容包含求职者姓名、性别、年龄和工作经历等;不同简历的工作经历希望有所不同,同时尽量减少重复代码。按下图设计,采用(44)模式,声明复制自身的接口。原题另写“由xx实例指定创建对象的种类”“通过复制这些Resume xx WorkExperience的对象来创建新的对象”。该模式属于(45)模式。

请作答:第45题。

  • A.

    混合型

  • B.

    行为型

  • C.

    结构型

  • D.

    创建型

答案与解析

平台答案:D。

整理解析

该设计通过复制已有对象产生新的简历和工作经历对象,解决对象如何创建的问题,属于创建型模式,选D。

补充与纠错

原页已核实:题面两处xx确为原网页文字,均保留原样。本题的第45空询问模式分类,第44空则询问模式名称,应区分两个问题。

2023-05 Q046

来源:第 46 题(原站入口)。

旅游公司开发软件,需要按季节、节假日等选择旅行定价方案,例如淡季折扣和一口价。适合采用(46)模式,该模式的主要意图是(47)。

请作答:第46题。

  • A.

    策略(Strategy)

  • B.

    状态(State)

  • C.

    观察者(Observer)

  • D.

    命令(Command)

答案与解析

平台答案:A。

整理解析

把不同定价规则分别封装,再依据季节、节假日选择使用哪一条规则,符合可替换算法的策略模式,选A。它强调选择定价算法,不是单纯因对象内部状态转移而改变行为。

2023-05 Q047

来源:第 47 题(原站入口)。

旅游公司开发软件,需要按季节、节假日等选择旅行定价方案,例如淡季折扣和一口价。适合采用(46)模式,该模式的主要意图是(47)。

请作答:第47题。

  • A.

    将一个请求封装为对象,从而可以用不同的请求对客户进行参数化

  • B.

    当一个对象的状态发生改变时,依赖于它的对象都得到通知并被自动更新

  • C.

    允许一个对象在其内部状态改变时改变它的行为

  • D.

    定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换

答案与解析

平台答案:D。

整理解析

把不同定价算法分别封装,使调用方通过统一接口替换所用算法,是此设计的主要意图,选D。A描述命令,B描述观察者,C描述状态。实现策略可以用对象,也可以用函数等形式,不强制要求只能靠继承。

2022年下半年软件设计师案例真题:案例题

本节保留 3 条来源,答案与解析默认收起。

2022-11-case Q003

温度换算界面的用例与类图

温度控制模块的界面提供华氏度(原文Farechet)与摄氏度(Celsius)两种单位。在任一输入框输入温度时,另一单位的数值会自动换算并显示。用户可用Raise、Lower按钮升高或降低温度;右侧温度计把数值按刻度比例显示,并随温度同步变化。

图3-1 温度控制界面及组件标注

面向对象分析得到以下用例图和类图。

图3-2 用例图

图3-3 类图

【问题1】(4分)填写图3-2的U1~U4用例名。

【问题2】(8分)使用图3-1中标注的词汇,填写图3-3的C1~C8类名。

【问题3】(3分)现要把界面改为通用GUI,支持任意计量单位的换算,如千克与磅、厘米与英寸。可在图3-3的类图中增加哪种设计模式?用不超过50字解释原因。

答案与解析

平台参考答案(原文保留)

【问题1】
U1:显示温度
U2:显示华氏度
U3:温度计显示
U4:温度计量换算
【问题2】
C1:TemperatureCovertorDialog
C2C4:
FahrenheitEditBox
CelsiusEditBx
TemperatureBar
C5
C8:
FahrenheitRaise
FahrenheitLower
CelsiusRaise
CelsiusLower
【问题3】
策略模式
原因:多种单位之间不同的换算规则可以写成不同的算法策略,这些算法之间是平等关系,可以根据自己的需求选择不同的策略,并且可以灵活切换。策略模式的功能就是把具体的算法实现,从具体的业务处理里面独 立出来,把它们实现成为单独的算法类,从而形成一系列的算法,并让这些算法可以相互替换。

解析与纠错

U1为显示温度,U2为显示华氏度,U3为温度计显示,U4为温度计量换算。用例图中的空心三角箭头表示U2、显示摄氏度、U3对U1的泛化;输入、升高、降低温度与U1之间,以及数值显示与换算之间,才是图中标注的include关系。平台解析把泛化与“包含”混用,应按实际箭头区分。

C1可按图3-1标注写TemperatureCovertorDialog。C2~C4为FahrenheitEditBox、CelsiusEditBox、TemperatureBar;C5~C8为FahrenheitRaise、FahrenheitLower、CelsiusRaise、CelsiusLower。类图在两个组内没有进一步区分位置,组内采用一致的对应即可;平台列出的CelsiusEditBx漏了字母o,与界面标注CelsiusEditBox不同。原图还将按钮父类标为Bottom,整理实现时应统一为Button,题图保留原样。

新增模式采用策略模式。符合50字限制的理由可写:“封装不同单位的换算算法为可替换策略,让界面按需要选择,增加换算规则时无需改动界面。”例如摄氏与华氏换算为F=9C/5+32、C=5(F−32)/9,规则应与界面显示分离。

图中Widget一端的实心菱形与通常由对话框拥有部件的含义相反;C1一侧拥有各部件的关系仍可支持本题填空。这里不以错误的菱形方向推导部件拥有对话框。

2022-11-case Q005

医院就医流程的Java程序填空

医院患者原本须分别与挂号、门诊、取药等部门交互。采用Facade(外观)模式,设置接待员代患者完成这些步骤,使患者只需面对一个一致的接口。图5-1为该场景的类图。

图5-1 类图

【Java代码】

import java.util.*;  
interface Patient{  
(1);  
}  
interface Disposer{  
(2);  
}  
class Registry implements Disposer{ //挂号  
public void dispose(Patient patient){  
System.out.println("I am registering..."+patient.getName());  
}  
}  
class Doctor implements Disposer{ //医生门诊  
public void dispose(Patient patient){  
System.out.println("I am diagnosing..."+patient.getName());

}

}

class Pharmacy implements Disposer{

public void dispose(Patient patient){

System.out.println("I am giving medicine..."+patient.getName());

}

}

class Facade{

private Patient patient;

public Facade(Patient patient){ this.patient = patient; }

public void dispose(){

Registry registry = new Registry();

Doctor doctor = new Doctor();

Pharmacy ph = new Pharmacy();

registry.dispose(patient);

doctor.dispose(patient);

ph.dispose(patient);

}

}

class ConcretePatient implements Patient{

private String name;

public ConcretePatient(String name){this.name = name;}

public String getName(){ return name;}

}

class FacadeTest{

public static void main(String[] args){

Patient patient = (3);

(4) f = (5);

(6);

}

}

根据说明和Java代码填写(1)~(6)。

答案与解析

平台参考答案(原文保留)

1:String getName()

2:void dispose(Patient patient)

3:new ConcretePatient(“abc”) //这里参数是合法字符串即可

4:Façade

5:new Facade(patient)

6:f.dispose()

解析与纠错

六空的可编译写法为:(1)String getName();(2)void dispose(Patient patient);(3)new ConcretePatient("abc"),字符串可替换为其它合法字符串;(4)Facade;(5)new Facade(patient);(6)f.dispose()。题干各空后已经给出分号,填空时不必重复。

Patient提供姓名查询,Disposer统一各部门的处理操作。Facade保存同一位患者,并依次调用Registry、Doctor、Pharmacy,分别完成挂号、门诊和取药;客户端只需构造Facade再调用dispose,不必直接组织三个部门。

原站可见页面已核实:Registry implements Disposer后确为全角{;原类和构造器均名为Facade,而平台第(4)空确为带ç的Façade。这是不同的Java标识符,应按原类声明使用Facade;全角{须在整理实现中改为半角{。平台答案中的全角方法括号和中文字符串引号同样需换成代码所需的半角符号。原题及平台答案保留原样,不能仅填入平台字符串就声称原段可编译;上述改动仅属于整理修正。

2022-11-case Q006

医院就医流程的C++程序填空

医院患者原本须分别与挂号、门诊、取药等部门交互。采用Facade(外观)模式,以接待员作为统一接口,代患者完成就医步骤,简化对多个子系统的访问。图6-1为该场景的类图。

图6-1 类图

【C++代码】

#include <iostream>

#include <string>

using namespace std;

class Patient{

public:

(1)

};

class Disposer{

public:

(2)

};

class Registry:public Disposer{ //挂号

public:

void dispose(Patient *patient){

cout << "I am registering...." << patient->getName() << endl;

}

};

class Doctor: public Disposer{ // 医生门诊

public:

void dispose(Patient *patient){

cout << "I am diagnosing..." << patient->getName() << endl;

}

};

class Pharmacy: public Disposer{ //取药

public:

void dispose(Patient *patient) {

cout << "I am giving medicine..." << patient->getName() << endl;

}

};

class Facade {

private:

Patient *patient;

public:

Facade(Patient *patient){this->patient=patient;}

void dispose(){

Registry *registry=new Registry();

Doctor *doctor= new Doctor();

Pharmacy *ph=new Pharmacy();

registry->dispose(patient);

doctor->dispose(patient);

ph->dispose(patient);

}

};

class ConcretePatient: public Patient {

private:

string name;

public:

ConcretePatient(string name){this->name=name;}

string getName(){return name;}

};

int main(){

Patient *patient=(3);

(4) f=(5);

(6);

return();

}

根据说明和C++代码填写(1)~(6)。

答案与解析

平台参考答案(原文保留)

1、virtual string getName()=0
2、virtual void dispose(Patient *patient)=0
3、new ConcretePatient("abc")//参数是合法字符串即可
4、Facade *
5、new Facade(patient)
6、f- > dispose()

解析与纠错

六空的可编译写法为:(1)virtual string getName()=0;;(2)virtual void dispose(Patient *patient)=0;;(3)new ConcretePatient("abc");(4)Facade *;(5)new Facade(patient);(6)f->dispose()。前两空的行末原段未给分号,完整声明必须把分号写在空内;(3)~(6)沿用题干已有分号。

Patient与Disposer通过纯虚函数定义接口,具体患者提供姓名,三个部门实现dispose。Facade保存患者指针并按挂号、诊断、取药顺序转交给相应部门。f是指针,所以用连续的->访问成员,不能将其拆成减号和大于号。

原站可见页面已核实:空(1)、(2)均单独成行,原代码及平台对应答案都没有分号;平台空(6)确为f- > dispose(),但解析文字另写为正确的f->dispose();原main结尾确为return(); },源码完整结束后进入知识点,未漏后续代码。前两处声明须补分号,成员访问须使用连续的->,int main的返回可整理为return 0;,也可直接运行到函数末尾。原错误写法保留;这些编译修正不冒充原题原文。

本段用new创建患者、外观及各部门对象却没有释放,反复调用会累积未回收对象。可在独立实现中使用自动对象或明确所有权的智能指针;若通过基类指针删除派生对象,还需适当的虚析构函数。这属于实现质量补充,不改变题目六空的模式与调用关系。

2022年上半年软件设计师应用技术:案例题

本节保留 3 组案例。

2022-05-case Q003

地址簿管理系统

阅读下列说明和图,回答问题1至问题3,将解答填入答题纸的对应栏内。

\[说明\]

某公司的人事部门拥有一个地址簿(AddressBook)管理系统(AddressBookSystem),用于管理公司所有员工的地址记录(PersonAddress)。员工的地址记录包括:姓名、住址、城市、省份、邮政编码以及联系电话等信息。

管理员可以完成对地址簿中地址记录的管理操作,包括:

(1)管理地址记录。根据公司的人员变动情况,对地址记录进行添加、修改、删除等操作。

(2)排序。按照员工姓氏的字典顺序或邮政编码对系统中的所有记录进行排序。

(3)打印地址记录。以邮件标签的格式打印一个地址单独的地址簿。

系统会对地址记录进行管理,为便于管理,管理员在系统中为公司的不同部门建立员工的地址簿的操作,包括:

(1)创建地址簿。新建一个地址簿并保存。

(2)打开地址簿。打开一个已有的地址簿。

(3)修改地址簿。对打开的地址簿进行修改并保存。

系统将提供一个GUI(图形用户界面)实现对地址簿的各种操作。

现采用面向对象方法分析并设计该地址簿管理系统,得到如图3-1所示的用例图和图3-2所示的类图。

图3-2 类图

[问题1](6分)

根据说明中的描述,给出图3-1中U1~U6所对应的用例名。

[问题2](5分)

根据说明中的描述,给出图3-2中类AddressBook的主要属性和方法以及类PersonAddress的主要属性(可以使用说明中的文字)。

[问题3](4分)

根据说明中的描述以及图3-1所示的用例图,请简要说明extend和include关系的含义是什么?

答案与解析

平台参考答案(原意保留)

【问题1】

U1:按姓氏字典顺序排序;U2:按邮政编码排序(其中U1和U2可互换);

U3:创建地址簿; U4: 修改地址簿; U5:打开地址簿; U6:保存地址簿。

【问题2】

类PersonAddress的主要属性包括:姓名、住址、城市、省份、邮政编码以及联系电话等。

类AddressBook的主要属性包括:部门名/编号,姓名、住址、城市、省份、邮政编码以及联系电话等。

类AddressBook的需要包括创建地址簿、打开地址簿、修改地址簿。综上,类AddressBook的方法包括:添加、修改、删除、创建、打开、打印、排序等。

【问题3】

extend属于用例图的三种关系之一,表示的是扩展关系。

描述为:如果一个用例明显地混合了两种或两种以上的不同场景,即根据情况可能会发生多种分支,则可以将这个用例分为一个基本用例和一个或多个扩展用例,关系图示指向为扩展用例指向基本用例。 如图所示,创建和打开就是一对扩展关系,创建成功之后可以直接保存关闭之后,如果想要进行后续修改工作,就需要打开地址簿,由扩展用例指向基本用例。

include属于用例图的三种关系之一,表示的是包含关系。

描述为:当可以从两个或两个以上用例中提取公共行为的时候,应该使用包含关系来表示它们。其中这个提取出来的公共用例称之为抽象用例,而把原始用例称为基本用例和基础用例。 如图所示:创建、修改和保存就是一对包含关系,在创建和修改它们都有公共的行为保存,提取出来称之为抽象用例,用包含关系表示它们。

解析与纠错

用例编号。 U1和U2分别为按姓氏字典顺序排序、按邮政编码排序,可以互换。U3为创建地址簿,U4为修改地址簿,U5为打开地址簿,U6为保存地址簿。U3、U4的include箭头都指向U6;图中extend箭头是 U5→U4,不是平台答案所说的“创建和打开”之间。

类的职责。 PersonAddress保存单条地址记录的姓名、住址、城市、省份、邮政编码、联系电话。AddressBook则宜保存部门名或编号,以及PersonAddress记录集合;不应把一套姓名、城市、电话等标量字段平铺到地址簿上,导致无法表达同一部门的多名员工。图中的组合关系也说明地址簿包含地址记录。

AddressBook主要业务方法可列添加、修改、删除地址记录,按姓氏/邮政编码排序、打印及保存。创建、打开、修改地址簿也是系统必须提供的操作;具体实现时,创建或打开可以由系统、工厂或持久化服务承担,不必把每个界面操作机械当作AddressBook实例方法。平台方法列表漏列“保存”,但创建和修改后保存已由题干及include关系明确要求。

include。 从基本用例指向被包含用例,把其所需的行为纳入基本用例。例如创建和修改都包含保存。它常用于复用共同步骤,但不要求一定由两个以上用例共享,也不使目标自动成为UML中的“抽象用例”。

extend。 从扩展用例指向被扩展的基本用例,在规定的扩展点及条件下追加行为,基本用例本身应能独立成立。图示可读作“打开”扩展“修改”;但题干没有明确扩展条件或扩展点,不能把“先打开才能修改”的普通前置条件直接当作extend的定义。平台对创建、打开、修改的时序解释不能替代UML语义。严格的泛化关系使用空心三角箭头,题图的排序变体应结合文字辨认,不宜把其简化箭头画法当作标准符号范本。

已回看原页确认,打印句确为“以邮件标签的格式打印一个地址单独的地址簿。”,没有遗漏后续句段。该句的范围表述含混,因此这里只列打印行为和邮件标签格式,不据此补出单条、整簿或批量范围。

2022-05-case Q005

状态保存与恢复(C++)

阅读下列说明和C++代码。将应填入(n)处的字句写在答题纸的对应栏内。
【说明】
在软件系统中,通常不会给用户提供取消、不确定或者错误操作的选择,允许将系统恢复到原先的状态。现使用备忘录(Memento)模式实现该要求,得到如图5-1所示的类图。Memento 包含了要被恢复的状态。Originator创建并在Memento中存储状态。Caretaker负责从Memento中恢复状态。

图5-1 类图

【C++代码】

#include <iostream>

#include <string>

#include <vector>

using namespace std;

class Memento {

private:

string state;

public:

Memento(string state) { this->state = state; }

string getState() { return state; }

};

class Originator {

private:

string state;

public:

void setState(string state) { this->state = state; }

string getState() { return state; }

Memento saveStateToMemento() {

return __(1)__;

}

void getStateFromMemento(Memento Memento) {

state = __(2)__;

}

};

class CareTaker {

private:

vector<Memento> mementoList;

public:

void __(3)__{mementoList.push_back(state);}

__(4)__{return mementoList[index];}

};

int main() {

Originator* originator = new Originator();

CareTaker* careTaker = new CareTaker();

originator->setState("State #1");

originator->setState("State #2");

careTaker->add(__(5)__);

originator->setState("State #3");

careTaker->add(__(6)__);

originator->setState("State #4");

cout << "Current State: " << "+" << originator->getState() << endl;

originator->getStateFromMemento(careTaker->get(0));

cout << "First saved State: " << "+" << originator->getState() << endl;

originator->getStateFromMemento(careTaker->get(1));

cout << "Second saved State: " << "+" << originator->getState() << endl;

return 0;

}
答案与解析

平台参考答案(原意保留)

(1)Memento(state)

(2)Memento.getState()
(3)add(Memento state)
(4)Memento get(int index)
(5)originator- > saveStateToMemento()
(6)originator- > saveStateToMemento()

解析与纠错

填空。 (1)Memento(state);(2)Memento.getState();(3)add(Memento state);(4)Memento get(int index);(5)(6)均为originator->saveStateToMemento()。这里返回和保存的是Memento值对象,所以(1)不应照搬Java的new。参数名Memento与类名同名虽不够清晰,但此处语法成立。

保存和恢复。 State #1之后立即设置为State #2,才第一次保存;第二次保存的是State #3。继续修改成State #4不会改写这两个历史快照。因此依次输出当前状态State #4、第一次保存状态State #2、第二次保存状态State #3。原C++输出字符串还显式拼接了一个“+”,它是显示字符,不是状态的一部分。

职责纠错。 Originator负责生成备忘录,并从备忘录恢复自己的状态;Memento保存快照;CareTaker保管和选择快照,可发起恢复请求,但不是实际修改Originator内部状态的对象。题干所写“Caretaker负责从Memento中恢复状态”不够准确。已回看原页确认,开头确为“通常不会给用户提供……”,与后面的允许恢复需求冲突;这里依据完整保存/恢复操作说明解题,不补造不存在的操作。

平台六空按C++标点填写即可运行给定示例。补充实现改用栈对象以避免原main中的两处new未释放,并用vector::at检查索引。快照按值保存,原对象后续修改、取得副本后再修改,都不应污染历史。C++17验证覆盖原示例、独立快照、副本修改、重复恢复、空串、中文状态和越界索引。

补充与完整参考实现

以下是按题意编写并验证的完整修正示例,含填空之外的语法修正与边界处理。

#include <iostream>
#include <string>
#include <utility>
#include <vector>

class Memento {
    std::string state;
public:
    explicit Memento(std::string value) : state(std::move(value)) {}
    std::string getState() const { return state; }
};
class Originator {
    std::string state;
public:
    void setState(std::string value) { state=std::move(value); }
    std::string getState() const { return state; }
    Memento saveStateToMemento() const { return Memento(state); }
    void getStateFromMemento(const Memento &memento) { state=memento.getState(); }
};
class CareTaker {
    std::vector<Memento> mementoList;
public:
    void add(Memento state) { mementoList.push_back(std::move(state)); }
    Memento get(std::size_t index) const { return mementoList.at(index); }
};
#ifndef MEMENTO_NO_MAIN
int main() {
    Originator originator;
    CareTaker careTaker;
    originator.setState("State #1");
    originator.setState("State #2");
    careTaker.add(originator.saveStateToMemento());
    originator.setState("State #3");
    careTaker.add(originator.saveStateToMemento());
    originator.setState("State #4");
    std::cout << "Current State: +" << originator.getState() << '\n';
    originator.getStateFromMemento(careTaker.get(0));
    std::cout << "First saved State: +" << originator.getState() << '\n';
    originator.getStateFromMemento(careTaker.get(1));
    std::cout << "Second saved State: +" << originator.getState() << '\n';
}
#endif

2022-05-case Q006

状态保存与恢复(Java)

阅读下列说明和Java代码,将应填入(n)处的字句写在答题纸的对应栏内。
【说明】
在软件系统中,通常都会给用户提供取消、不确定或者错误操作的选择,允许将系统恢复到原先的状态。现使用备忘录(Memento)模式实现该要求,得到如图6-1所示的类图。Memento包含了要被恢复的状态。Originator创建并在Memento中存储状态。Caretaker负责从Memento中恢复状态。

图6-1 类图

【Java代码】

import java.util.*;

class Memento {

private String state;

public Memento(String state){this.state=state;}

public String getState(){return state;}

}

class Originator{

private String state;

public void setState(String state){this.state=state;}

public String getState(){ retum state;}

public Memento saveStateToMemento( ){

return (1);

}

public void getStateFromMemento(Memento Memento){

state =(2);

}

}

class CareTaker{

private List < Memento > mementoList= new ArrayList < Memento > ();

public(3){

mementoList.add(state);

}

public (4){

return memensoList.get(index);

}

}

class MementoPaneDems{

public static void main(String[] args) {

Originator originator =new Originator();

CareTaker careTaker=new careTaker();

originator.setState("State #1");

originator.setState("State #2");

careTaker.add( (5) );

originator.setState("State #3");

careTaker.add( (6) );

originator.setState("State #4");

System.out.println("Current State"+originator.getState());

originator.getStateFromMemento(careTaker.get(0));

System.out.println("Frist saved State"+originator.getState());

originator.getStateFromMemento(careTaker.get(1));

System.out.println("Second saved State"+originator.getState());

}

}
答案与解析

平台参考答案(原意保留)

(1) new Memento(state)
(2) Memento.getState()
(3) void add(Memento state)
(4) Memento get(int index)
(5) originator.saveStateToMemento()
(6) originator.saveStateToMemento()

解析与纠错

填空。 (1)new Memento(state);(2)Memento.getState();(3)void add(Memento state);(4)Memento get(int index);(5)(6)均为originator.saveStateToMemento()。Java构造对象需要new;第(3)处前面只有public,故还需void,不能直接照搬C++题的空位内容。

快照保存时点与C++题一致:先保存State #2,再保存State #3,当前值最终为State #4;恢复第0、第1项后分别得到State #2和State #3。String不可变,把当前字符串引用保存到一个独立Memento后,后续给Originator.state重新赋值不会更改之前的快照。

非空号错误。 已回看原页确认,六空答案本身正确,但原代码确含全角标点;retum应为return,memensoList应为mementoList,new careTaker()应按类名写成new CareTaker()。Frist saved State只是输出文案的拼写错误,补充实现也统一为First。只填空而不修正这些非空号错误,程序仍无法编译。

与C++题相同,实际恢复职责在Originator,CareTaker负责保存/取得Memento。补充示例为Memento的状态字段加final以明确快照不可变;初始空串和拒绝null是该示例选定的边界行为,不作为原题隐含条件。Java21验证原例、历史快照稳定性、重复恢复、空串和中文状态,以及越界索引、空状态和空备忘录参数。

补充与完整参考实现

以下是按题意编写并验证的完整修正示例,含填空之外的语法修正与边界处理。

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

final class Memento {
    private final String state;
    public Memento(String state) { this.state=Objects.requireNonNull(state, "state"); }
    public String getState() { return state; }
}
class Originator {
    private String state="";
    public void setState(String state) { this.state=Objects.requireNonNull(state, "state"); }
    public String getState() { return state; }
    public Memento saveStateToMemento() { return new Memento(state); }
    public void getStateFromMemento(Memento memento) {
        state=Objects.requireNonNull(memento, "memento").getState();
    }
}
class CareTaker {
    private final List<Memento> mementoList=new ArrayList<>();
    public void add(Memento state) { mementoList.add(Objects.requireNonNull(state, "memento")); }
    public Memento get(int index) { return mementoList.get(index); }
}
public class MementoPatternDemo {
    public static void main(String[] args) {
        Originator originator=new Originator();
        CareTaker careTaker=new CareTaker();
        originator.setState("State #1");
        originator.setState("State #2");
        careTaker.add(originator.saveStateToMemento());
        originator.setState("State #3");
        careTaker.add(originator.saveStateToMemento());
        originator.setState("State #4");
        System.out.println("Current State"+originator.getState());
        originator.getStateFromMemento(careTaker.get(0));
        System.out.println("First saved State"+originator.getState());
        originator.getStateFromMemento(careTaker.get(1));
        System.out.println("Second saved State"+originator.getState());
    }
}

2021年下半年软件设计师案例真题:案例题

本节保留 3 条来源,答案与解析默认收起。

2021-11-case Q003

吃金币游戏的用例与类图

某游戏公司开发吃金币游戏。背景是回廊式迷宫Maze,迷宫不同位置设有墙;机器人Robots分为小精灵PacMan与幽灵Ghost。玩家控制小精灵在迷宫路径上吞吃金币,并避免被幽灵抓到;幽灵会在迷宫内游走,吃掉遇到的小精灵。游走路径长度按单位距离的倍数计算,迷宫中至少有一个小精灵和一个幽灵时游戏开始。

每个机器人具有两种传感器:

  1. 前向传感器FrontSensor探测当前位置左侧、右侧、前方是否有墙。遇墙必须改变方向,机器人依据探测结果决定运动方向。
  2. 近距离传感器ProxiSesor探测视线范围内、正前方是否有隐藏的金币或幽灵。它不直接报告对象是否移动及移动方向;若连续两次探测显示对象位置不同,可推断对象正在移动。

每个机器人还有一个计时器Timer,用来支持预先定义的定时事件。机器人的动作包括原地向左或向右旋转90°,以及向前或向后移动。

用户可用编辑器Editor编写迷宫文件,并把文件导入游戏系统,建立自定义迷宫。采用面向对象分析与设计,得到图3-1用例图和图3-2初始类图。

【问题1】(3分)根据说明,填写图3-1中U1~U3的用例名。

【问题2】(4分)U1~U3分别与哪些用例有关系?各是什么关系?

【问题3】(8分)根据说明,填写图3-2中C1~C8的类名。

答案与解析

平台参考答案(原文保留)

【问题1】(3分)

U1编写迷宫文件;

U2导入迷宫文件;

U3设置计时器。
或者
U1是导入文件,U2,U3分别是旋转、移动

【问题2】(4分)
U1和U2与建立迷宫用例是泛化关系;U3与操作机器人是包含关系。
或者
导入文件与建立迷宫是包含关系。
旋转、移动 和 操作机器人 是泛化关系。
【问题3】(8分)
C1 机器人(Robots);C2 计时器(Timer);C3小精灵(PacMan);C4幽灵(Ghost) ; C5 传感器(Sensor) ; C6 前向传感器(FrontSensor) ; C7 近距离传感器(ProxiSesor); C8 迷宫(Maze)

其中C3与C4可换;C6与C7可换

解析与纠错

类图部分可以从泛化和整体—部分关系确定:C1为Robots,C3、C4为PacMan与Ghost;C5为Sensor,C6、C7为FrontSensor与ProxiSesor;每个机器人对应一个计时器,故C2为Timer;聚合多个机器人的C8为Maze。C3与C4、C6与C7可各自对换,但应成对保持一致。图中的2..*只保证机器人总数至少为2;“至少一个小精灵和一个幽灵”还需要附加业务约束,不能只靠该多重性表达。

用例部分的平台答案本身提供两套方案:第一套把U1、U2、U3分别解释为编写迷宫文件、导入迷宫文件、设置计时器;第二套把它们解释为导入文件、旋转、移动。原图的U1~U3均没有连线,文字也没有唯一规定它们的位置对应关系,所以不能仅按椭圆之间的距离认定某一套是唯一答案。

按UML含义,include表示执行基础用例时必须包含的行为,泛化表示特殊用例继承一般用例的行为与关系。建立自定义迷宫的文字描述是编写后导入,不足以证明“编写”和“导入”是可替代的两种建立方式;题面也没有说每次操作机器人都必须设置计时器。因而平台第一套的两项泛化及计时器包含关系都依赖额外假设。若把旋转、移动抽象为操作机器人的特殊用例,可以讨论第二套泛化,但仍不是原图直接给出的唯一结论。平台解析将“建立迷宫”称为特殊用例也不符合其所主张的泛化方向;若采用该方案,它应是一般用例。

2021-11-case Q005

围棋程序的C++填空

享元(flyweight)模式通过减少创建对象的数量来降低内存占用、提高性能。现开发允许多个玩家联机对弈的网络围棋程序;只有一台服务器,为节省内存,题设采用享元模式实现。图5-1给出类图。

阅读以下C++代码,将空(1)~(5)应填的字句写出。

#include <iostream>

#include <vector>

#include <string>

using namespace std;

enum PieceColor { BLACK, WHITE }; // 棋子颜色

class PiecePos { // 棋子位置

private:

int x;

int y;

public:

PiecePos(int a, int b): x(a), y(b) {}

int getX() { return x; }

int getY() { return y; }

};

class Piece { // 棋子定义

protected:

PieceColor m_color; // 颜色

PiecePos m_pos; // 位置

public:

Piece(PieceColor color, PiecePos pos): m_color(color), m_pos(pos) {}

(1);

};

class BlackPiece: public Piece {

public:

BlackPiece(PieceColor color, PiecePos pos): Piece(color, pos) {}

void Draw() { cout << " draw a black piece " << endl; }

};

class WhitePiece: public Piece {

public:

WhitePiece(PieceColor color, PiecePos pos): Piece(color, pos) {}

void Draw() { cout << " draw a white piece " << endl; }

};

class PieceBoard {

private:

vector< (2) > m_vecPiece; // 棋盘上已有的棋子

string m_blackName; // 黑方名称

string m_whiteName; // 白方名称

public:

PieceBoard(string black, string white): m_blackName(black), m_whiteName(white) {}

void SetPiece(PieceColor color, PiecePos pos) { // 一步棋,在棋盘上放一颗棋子

(3) piece = NULL;

if (color == BLACK) { // 放黑子

piece = new BlackPiece(color, pos); // 获取一颗黑子

cout << m_blackName << "在位置(" << pos.getX() << ',' << pos.getY() << ")";

(4);

} else { // 放白子

piece = new WhitePiece(color, pos); // 获取一颗白子

cout << m_whiteName << "在位置(" << pos.getX() << "," << pos.getY() << ")";

(5);

}

m_vecPiece.push_back(piece);

}

};
答案与解析

平台参考答案(原文保留)

(1) virtual void Draw()=0
(2) Piece*
(3) Piece *
(4) piece- > Draw()
(5) piece- > Draw()

解析与纠错

(1)填virtual void Draw()=0,声明由具体棋子实现的纯虚函数;(2)、(3)都填Piece*,使容器和局部变量可以保存黑棋、白棋的基类指针。(4)、(5)按有效C++语法均应写piece->Draw(),由虚函数动态绑定调用相应棋子的绘制方法。

原页已核实:平台第(4)、(5)空确写为piece- > Draw()。其中的空格把->拆成两个运算符,原样代入会编译失败;上面的->是整理修正,平台答案仍保留其原写法。仅修正这两处箭头后,填空代码可编译,运行验证了黑白棋子的动态分派和位置输出。

题设称使用享元模式,但此代码每次SetPiece都new一个棋子,并把位置m_pos存进对象,没有对象复用或享元工厂;相同颜色连续落子得到的也是不同对象。它展示了继承、容器和多态,不能据此证明减少了棋子对象数。若真正采用享元,应共享与位置无关的棋子内部状态,将棋盘、坐标等外部状态交给各次使用者管理。这个设计修正不是原题填空,不能拿改写后的代码冒充原程序。

此外,代码未定义原始指针的释放责任;若后来通过Piece*删除派生对象,应为基类添加虚析构或采用正确的所有权设计。原题未提供这些管理代码,填对五空并不等于程序已具备完整的内存管理。

原题在m_vecPiece.push_back(piece);及方法、类的闭合符号之后即结束,没有后续工厂或对象复用代码;两个分支分别new BlackPiece、new WhitePiece。上述实现限制已由完整题面确认。

2021-11-case Q006

围棋程序的Java填空

享元(flyweight)模式通过减少创建对象的数量来降低内存占用、提高性能。现开发允许多个玩家联机对弈的网络围棋程序;只有一台服务器,为节省内存,题设采用享元模式实现。图6-1给出类图。

阅读以下Java代码,将空(1)~(5)应填的字句写出。

import java.util.*;

enum PieceColor {BLACK,WHITE} //棋子颜色

class PiecePos { //棋子位置

private int x;

private int y;

public PiecePos(int a,int b){

x=a;

y=b;

}

public int getX( ){

return x;

}

public int getY( ){

return y;

}

}

abstract class Piece { //棋子定义

protected PieceColor m_color; //颜色

protected PiecePos m_pos; //位置

public Piece(PieceColor color,PiecePos pos){

m_color=color;

m_pos=pos;

}

(1);

}

class BlackPiece extends Piece{

public BlackPiece(PieceColor color,PiecePos pos){

super(color,pos);

}

public void draw ( ) {

System.out.println("draw a black piece");

}

}

class WhitePiece extends Piece{

public WhitePiece(PieceColor color,PiecePos pos){

super(color,pos);

}

public void draw( ) {

System.out.println("draw a white piece");

}

}

class PieceBoard{

//棋盘上已有的棋子

private static final ArrayList<(2)> m_arrayPiece=new ArrayList();

private String m_blackName; //黑方名称

private String m_whiteName; //白方名称

public PieceBoard(String black,String white){

m_blackName=black;

m_whiteName=white;

}

//一步棋,在棋盘上放一颗棋子

public void SetePiece(PieceColor color,PiecePos pos){

(3) piece=null;

if(color==PieceColor.BLACK){ //放黑子

piece=new BlackPiece(color,pos); //获取一颗黑子

System.out.println(m_blackName+"在位置("+pos.getX()+","+pos.getY()+")");

(4);

}

else{ //放白子

piece=new WhitePiece(color,pos); //获取一颗白子

System.out.println(m_whiteName+"在位置("+pos.getX()+","+pos.getY()+")");

(5);

}

m_arrayPiece.add(piece);

}

}
答案与解析

平台参考答案(原文保留)

(1)public abstract void draw( )
(2)Piece
(3)Piece
(4)piece.draw( )
(5)piece.draw( )

解析与纠错

(1)为public abstract void draw(),声明无方法体的抽象方法;语句末尾分号已经在空外。(2)、(3)均为Piece,分别作ArrayList的元素类型和局部引用类型。(4)、(5)均为piece.draw(),运行时根据实际对象调用BlackPiece或WhitePiece的实现。

填入平台答案后可以编译,原代码new ArrayList()使用原始类型,会产生未经检查转换的警告;写成new ArrayList<>()可消除该警告,这是整理建议,不改原题。SetePiece虽不是通常的拼法,却是合法方法名,调用时应与声明一致。

原代码每次落子都new一个棋子,不复用同色对象;静态m_arrayPiece仅让所有棋盘对象共享同一个列表,不能使列表内的棋子变成享元。测试建立两个棋盘后,两者访问到同一列表;同色落子的对象身份仍不同。若该字段按注释表示“棋盘上已有的棋子”,多个棋局还会混入同一容器,应把每盘的落子记录与可跨棋盘共享的棋子内部状态分开。题设的享元目标与现有实现存在差距,不能将静态集合等同于已经实现了享元模式。

原页已核实列表声明确为private static final ArrayList<(2)> m_arrayPiece=new ArrayList();。SetePiece的两个分支分别new棋子,代码在m_arrayPiece.add(piece);及方法、类的闭合符号之后结束,没有后续代码。静态列表及缺少对象复用均是完整原题的写法。

2022年上半年软件设计师基础知识真题

本节新增5道题,沿用本卷原题号;答案与解析默认收起。

2022-05 Q062

来源:第62题(原站入口)。

UML序列图描绘以(62)顺序组织的对象交互。观察下图,(63)表示返回消息;题面写作“Accoun t”的类应实现的方法为(64)。

请作答:第62题。

  • A.

    活动

  • B.

    时间

  • C.

    消息

  • D.

    调用

答案与解析

平台答案:B。

整理解析

序列图强调交互事件的时间先后,纵向向下通常表示后续发生的事件,选B。水平方向用于区分参与者,不是另一条时间轴。

补充与纠错

普通序列图不要求纵向距离与实际耗时成比例;生命线上的事件顺序及消息约束也不必定义系统所有事件的唯一全序。图中类名为Account,题干的拆分拼写“Accoun t”保留。

2022-05 Q063

来源:第63题(原站入口)。

UML序列图描绘以(62)顺序组织的对象交互。观察下图,(63)表示返回消息;题面写作“Accoun t”的类应实现的方法为(64)。

请作答:第63题。

  • A.

    tanslD

  • B.

    balance

  • C.

    withdraw

  • D.

    deposit

答案与解析

平台答案:B。

整理解析

从src对象返回管理器的第3条消息使用虚线返回箭头,标注Balance,对应选项B的balance;withdraw与deposit是发往Account对象的调用。

补充与纠错

图中文字首字母为大写Balance,选项为小写balance;按所指的返回值理解,原大小写和A的tanslD拼写均保留,不自行改写标识符。

2022-05 Q064

来源:第64题(原站入口)。

UML序列图描绘以(62)顺序组织的对象交互。观察下图,(63)表示返回消息;题面写作“Accoun t”的类应实现的方法为(64)。

请作答:第64题。

  • A.

    start()

  • B.

    checkBalance()和withdraw()

  • C.

    deposit()

  • D.

    checkBalance()、withdraw()和deposit()

答案与解析

平台答案:D。

整理解析

src、tgt都是Account对象:src接收checkBalance、withdraw,tgt接收deposit,因此Account需提供三种操作,选D。start消息发给管理器,不属于Account必须实现的方法。

补充与纠错

图中两个对象同属Account类,判断类的操作集合时要合并它们收到的相关调用;不要因每个对象只接收其中一部分就漏掉方法。

2022-05 Q067

来源:第67题(原站入口)。

对象状态变化时,使用(67)设计模式通知所有依赖它的监听者;使用(68)设计模式限制一个类只能有一个实例对象。

请作答:第67题。

  • A.

    责任链(chainofresponsibility)

  • B.

    命令(command)

  • C.

    抽象工厂(abstractfactory)

  • D.

    观察者(observer)

答案与解析

平台答案:D。

整理解析

对象维护依赖它的监听者,状态变化时发送通知,这是一对多依赖的观察者模式,选D。

补充与纠错

观察者与经消息代理解耦的发布订阅在实现结构上不总是相同;本题按直接通知依赖者的模式描述判断。

同材料解析参照来源第68题。

2022-05 Q068

来源:第68题(原站入口)。

对象状态变化时,使用(67)设计模式通知所有依赖它的监听者;使用(68)设计模式限制一个类只能有一个实例对象。

请作答:第68题。

  • A.

    原型(prototype)

  • B.

    工厂方法(factorymethod)

  • C.

    单例(singleton)

  • D.

    生成器(builder)

答案与解析

平台答案:C。

整理解析

单例模式控制一个类只提供一个实例,并提供相应访问方式,选C。工厂方法解决选择创建哪个具体类,原型通过复制构造对象,生成器分步骤构造复杂对象。

补充与纠错

唯一实例的范围要结合运行环境界定;线程安全、反射、序列化或多个加载器等因素不能仅凭模式名称自动得到保证。

2021年上半年软件设计师案例真题:案例题

本节保留 3 条来源,答案与解析默认收起。

2021-05-case Q003

线上抓药系统的用例与类图

某中医医院拟开发线上抓药APP,患者可凭本院医生开具的处方在线抓药,系统提供免费送药上门服务。主要功能如下。

  1. 注册:患者扫描医院二维码,提供病历号,系统据此自动取得患者基本信息。
  2. 登录:已注册患者可登录抓药,未注册者被拒绝登录。
  3. 确认处方:登录后可查看医生开具的所有处方,选择本次处方、药的副数,并说明是否煎制。取药可自行到店或送药上门;选择配送时提供收货人姓名、联系方式、收货地址。系统自动计算费用,患者可用微信、支付宝等方式支付;支付成功后,把处方送给药师配药。
  4. 处理处方:药师按处方配药,并按患者要求煎制;煎制完成后将处方设置为已完成。自行取药者取药后确认已取药。
  5. 药品派送:处方完成后,对于选择配送的患者,向快递人员发送药品配置信息,等待取药,同时向患者发送“收获验证码”。
  6. 送药上门:快递人员将药送至指定地址;患者“收获”时出示验证码,快递人员凭此确认已送达。

图3-1为用例图,图3-2为类图。

【问题1】(7分)填写图3-1中A1~A3的参与者名称,以及U1~U4的用例名称。

【问题2】(5分)填写图3-2中C1~C5的类名。

【问题3】(3分)简述用例之间include、extend、generalize关系的含义。

答案与解析

平台参考答案(原文保留)

【问题1】 A1:患者 A2:快递员 A3:药师 U1:确认处方 U2:支付 U3:微信支付 U4:支付宝支付 U3和U4可互换。 【问题2】 C1:支付方式 C2:微信支付 C3:支付宝支付 C4:处方 C5:派送信息 C2和C3可互换。 【问题3】 include(包含)包含关系:其中这个提取出来的公共用例称为抽象用例,而把原始用例称为基本用例或基础用例;当可以从两个或两个以上的用例中提取公共行为时,应该使用包含关系来表示它们。 本系统中,确认药方过程中系统会自动计算本次抓药的费用,患者可以使用微信或支付宝等支付方式支付费用,所以确认药方包含支付过程。 extend (扩展)扩展关系:如果一个用例明显地混合了两种或两种以上的不同场景,即根据情况可能发生多种分支,则可以将这个用例分为一个基本用例和一个或多个扩展用例,这样使描述可能更加清晰。 generalize(泛化)泛化关系:当多个用例共同拥有一种类似的结构和行为的时候,可以将它们的共性抽象成为父用例,其他的用例作为泛化关系中的子用例。在用例的泛化关系中,子用例是父用例的一种特殊形式,子用例继承了父用例所有的结构、行为和关系。 本系统中患者可以使用微信或支付宝等支付方式支付费用,即支付可以有不同种方式,包括微信支付、支付宝支付等,所以微信支付和支付宝支付是支付的特殊化,支付是二者的泛化。 注:本题分值较少,写明定义即可,可以不结合本题实例进行说明。

解析与纠错

注册、登录、确认处方由患者发起,所以A1是患者;参与配送和送达确认的是A2快递员;处理处方的是A3药师。U1为确认处方,所包含的U2为支付;泛化到U2的U3、U4分别为微信支付、支付宝支付,两者可互换。当前完整说明已明确快递人员及验证码流程,平台长解析中“A2线索不明确、当前未给出”的说法不适用于这份题面。

类图的C1为支付方式,其子类C2、C3为微信支付、支付宝支付,可互换;连接支付方式与药师的C4为处方,C5为派送信息。应保持每组父类、子类的语义一致。

include是基础用例在相应执行点必须包含被包含用例的行为,箭头从基础用例指向被包含用例;把公共行为抽出是常见用途,但不要求一定已有两个调用它的用例。extend是在扩展点按条件加入行为,基础用例本身可以独立成立,箭头从扩展用例指向基础用例,不能把任意分支都直接当作extend。generalize表示特殊用例继承一般用例的行为和关系,空心三角箭头指向一般用例,如微信支付、支付宝支付泛化到支付。

说明中的“收获验证码”“收获时”按业务含义应理解为收货验证及收货时,原写法保留。

2021-05-case Q005

层叠菜单的C++填空

层叠菜单常用于窗口式软件的功能组织。菜单内既可放直接对应功能的菜单项,也可放子菜单;本题用组合(composite)模式实现。图5-1为层叠菜单示例,图5-2为类图。

阅读以下C++代码,填写空(1)~(5)。

#include <list>

#include <iostream>

#include <string>

using namespace std;

class MenuComponent { //构成层叠菜单的元素

(1):

string name; //菜单项或子菜单名称

public:

void printMenu(){cout << name;}

(2);

virtual void removeMenuElement(MenuComponent *element)=0;

(3);

};

class MenuItem: public MenuComponent {

public:

MenuItem(string name){this->name=name;}

void addMenuElement(MenuComponent *element){return;}

void removeMenuElement(MenuComponent *element){return;}

list<MenuComponent *> *getElement(){return NULL;}

};

class Menu : public MenuComponent{

private:

(4);

public:

Menu(string name){this->name=name;}

void addMenuElement(MenuComponent *element)

{elementList.push_back(element);}

void removeMenuElement(MenuComponent *element)

{elementList.remove(element);}

list<MenuComponent *> *getElement(){return &elementList;}

};

int main(){

MenuComponent *mainMenu=new Menu("Insert");

MenuComponent *subMenu=new Menu("Chart");

MenuComponent *element =new MenuItem("On This Sheet");

(5);

subMenu->addMenuElement(element);

return 0;

}
答案与解析

平台参考答案(原文保留)

(1)protected

(2)virtual void addMenuElement(MenuComponent *element)=0

(3)virtual list < MenuComponent* >

(4)list < MenuComponent * > elementList

(5)mainMenu- > addMenuElement(subMenu)

解析与纠错

(1)按类图的#name填写protected;(2)应声明纯虚成员virtual void addMenuElement(MenuComponent *element)=0。(3)需要完整的纯虚接口virtual list<MenuComponent*> *getElement()=0,平台只给到virtual list < MenuComponent* >,缺少指针、函数名、参数表和纯虚标记,不能构成该成员声明。(4)为list<MenuComponent*> elementList。

(5)的平台意图是mainMenu->addMenuElement(subMenu),把Chart子菜单接到Insert主菜单;后面的subMenu->addMenuElement(element)再接入On This Sheet菜单项。平台答案中“- >”应是连续运算符“->”。

原题包含Menu类声明、构造器,以及mainMenu、subMenu的初始化,代码完整。按平台答案直接填空仍不能编译:第(2)空需将全角括号改为C++括号,第(3)空需补成完整纯虚接口,第(5)空需把箭头连写。仅作这些答案修正后,原main可编译运行;它只建立菜单树,没有输出语句,因此正常运行不输出文字。另加的测试验证了添加、移除、叶子无子节点及递归遍历Insert→Chart→On This Sheet,递归打印属于测试扩展。

Menu与MenuItem都实现MenuComponent,使调用者可以统一处理子菜单与菜单项,符合组合模式。原代码采用不负责销毁对象的裸指针集合;若扩展到动态对象回收,还需明确所有权及基类虚析构,不能据此认为原题已解决内存管理。

原页已核实第(3)空答案只到virtual list < MenuComponent* >,第(5)空答案确为mainMenu- > addMenuElement(subMenu);上方保留原题代码的写法。题干在return 0;及main的闭括号后完整结束。

2021-05-case Q006

层叠菜单的Java填空

层叠菜单常用于窗口式软件的功能组织。菜单内既可放直接对应功能的菜单项,也可放子菜单;本题用组合(composite)模式实现。图5-1为层叠菜单示例,图5-2为类图。

阅读以下Java代码,填写空(1)~(5)。

import java.util.*;

abstract class MenuComponent { // 构成层叠菜单的元素

(1) String name; // 菜单项或子菜单名称

public void printName() { System.out.println(name); }

public (2);

public abstract boolean removeMenuElement(MenuComponent element);

public (3);

}

class MenuItem extends MenuComponent {

public MenuItem(String name) { this.name=name; }

public boolean addMenuElement(MenuComponent element) { return false; }

public boolean removeMenuElement(MenuComponent element){ return false; }

public List<MenuComponent> getElement(){ return null; }

}

class Menu extends MenuComponent {

private (4);

public Menu(String name){

this.name = name;

this.elementList = new ArrayList<MenuComponent>();

}

public boolean addMenuElement(MenuComponent element){

return elementList.add(element);

}

public boolean removeMenuElement(MenuComponent element){

return elementList.remove(element);

}

public List<MenuComponent> getElement() {return elementList;}

}

class CompositeTest {

public static void main(String[] args) {

MenuComponent mainMenu = new Menu("Insert");

MenuComponent subMenu = new Menu("Chart");

MenuComponent element = new MenuItem("On This Sheet");

(5);

subMenu.addMenuElement(element);

printMenus(mainMenu);

}

private static void printMenus(MenuComponent ifile){

ifile.printName();

List<MenuComponent> children = ifile.getElement();

if(children == null) return; //打印

for(MenuComponent element: children){

printMenus(element);

}

}

}
答案与解析

平台参考答案(原文保留)

(1)protected
(2)abstract boolean addMenuElement(MemuComponent element)
(3)abstract List < MenuComponent > getElement()
(4)ArrayList < MenuComponent > elementList
(5)mainMenu.addMenuElement(subMenu)

解析与纠错

类图中的#name对应(1) protected;(2)应为abstract boolean addMenuElement(MenuComponent element),(3)为abstract List<MenuComponent> getElement()。(4)可按平台写ArrayList<MenuComponent> elementList,其构造器创建ArrayList;声明为接口类型List<MenuComponent>也与现有赋值和方法调用兼容。

(5)为mainMenu.addMenuElement(subMenu)。先把Chart接入Insert,再把On This Sheet接入Chart,printMenus按先当前节点、后子节点的顺序输出三行:Insert、Chart、On This Sheet。

平台第(2)空把参数类型写为MemuComponent,而原类名是MenuComponent;这会导致找不到符号,必须区分原答案与正确拼法。只把该字母错误改正后,给定Java程序可编译,原main输出与预期一致,添加、移除、空子列表和叶子行为测试也通过。叶子返回null、add/remove返回false;组合节点维护子元素列表,由统一接口支持递归遍历。

原页已核实平台第(2)空确写MemuComponent,属于原答案拼写问题。题干在printMenus递归方法及CompositeTest的闭括号之后完整结束,没有遗漏后续代码。

2020年软件设计师案例真题:案例题

本节保留 3 条来源,答案与解析默认收起。

2020-case Q003

房产信息系统的用例与类图

某房产公司拟开发房产信息管理系统,需求如下。

  1. 房产Property分为住宅House、公寓Cando。每套房产保存房产证明、地址、建造年份、建筑面积、销售报价、房产照片、销售状态(在售、售出、停售)。住宅另存楼层、公摊面积、是否有地下室;公寓另存是否有阳台。
  2. 公司雇佣多名房产经纪Agent销售房产,记录姓名、家庭住址、联系电话、受雇起止时间。一套房产在同一时段只由一名经纪负责;系统另记录经纪负责每套房产的起始时间、终止时间。
  3. 用户User包括房产经纪与系统管理员Manager,必须通过身份验证后才能登录。经纪可录入、查询本人负责的房产信息;修改本人负责的房产信息须经管理员审批授权。
  4. 管理员可导出所有房产的信息报表,定期归档已售出和停售的房产。公司确定不再销售某套房产时,由管理员删除其信息。

图3-1为用例图,图3-2为初始类图。

【问题1】(7分)(1)填写图3-1参与者A1、A2及用例U1~U3的名称;(2)填写图中(a)、(b)处的用例关系。

【问题2】(6分)填写图3-2中C1~C6的类名。

【问题3】(2分)图3-2用AgentList进一步阐述C1、C6之间的关系;根据需求绘出其主要属性。

答案与解析

平台参考答案(原文保留)

【问题1】(7分)
A1:房产经纪;A2:系统管理员
U1:审批授权;U2:修改房产信息;U3:删除房产信息
(a): < < include > > ;(b): < < extend > >
【问题2】 (6分)
C1: Property C2: House C3: Cando C4: User C5:Manager C6:Agent
【问题3】(2分)
AgentList的主要属性有:房产经纪负责该房产的起始时间和结束时间

解析与纠错

A1为房产经纪,A2为系统管理员;U1为审批授权,U2为修改房产信息,U3为删除房产信息。(a)从修改指向审批,按题图填include:修改必须包含审批授权,不能据此理解为平台解析所说的“先修改,再审批”;授权应先于修改生效。(b)从删除指向归档,按图填extend,表示满足不再销售等条件时加入删除行为。需求文字并未进一步规定所有删除都必须先归档,该关系是本题图采用的建模表达。

C1~C6依次为Property、House、Cando、User、Manager、Agent;Cando沿用原题类名,不擅改为常见拼法Condo。左侧House、Cando指向Property的空心三角表示继承,方向正确;右侧原图却把空心三角画向C5、C6,与用户角色的语义相反。应由Manager、Agent的泛化箭头指向父类User,即C4。原图保留,不能按错误箭头倒置父子类。平台解析也提示了该图错误。

AgentList通过虚线挂在Property与Agent的关联上,表示关联类;主要属性是经纪负责该套房产的起始时间、终止时间。它们不同于经纪自身的受雇起止时间,也不是房产建造年份。同一房产的负责时段不能重叠,才能满足“同一时段仅一名经纪”的条件。

2020-case Q005

在线支付的Java填空

在线支付需要对接不同电子商务平台的接口。希望客户在不同平台购物时,无须关心具体支付接口,因此采用中介者(Mediator)模式整合。图6-1给出类图。

阅读Java代码,填写空(1)~(5)。

import java.util.*;  

interface WebServiceMediator {  
public (1);  
public void SetAmazon(WebService amazon);  
public void SetEbay(WebService ebay);  
}  
abstract class WebService{  
protected (2) mediator;  
public abstract void SetMediator(WebServiceMediator mediator);  
public (3);  
public abstract void search(double money);  
}  
class ConcreteServiceMediator implements WebServiceMediator{  
private WebService amazon;  
private WebService ebay:  
public ConcreteServiceMediator() {  
amazon = null;  
ebay = null;  
}  
public void SetAmazon(WebService amazon) {  
this.amazon-amazon:  
}  
public void SetEbay(WebService ebay){  
this.ebay=ebay;  
}  
public void buy(double money,WebService service){  
if(service==amazon)  
amazon.search(money);  
else  
ebay.search(money);  
}  
}  
class Amazon extends WebService {  
public void SetMediator(WebServiceMediator mediator) {  
this.mediator = mediator:  
}  
public void buyService(double money) {  
(4);  
}  
public void search(double money){  
system.out.println("Amazon receive:"+money);  
}  
}  
class Ebay extends WebService{  
public void SetMediator(WebServiceMediator mediator) {  
this. mediator = mediator;  
}  
public void buyService(double money){  
(5);  
}  
public void search(double money){  
System.out.println("Ebay receive: "+money);  
}

}
答案与解析

平台参考答案(原文保留)

(1) void buy(double money, WebService service)
(2) WebServiceMediator
(3) abstract void buyService(double money)
(4) mediator.buy(money, this)
(5) mediator.buy(money, this)

解析与纠错

(1)为void buy(double money, WebService service),在中介者接口中声明统一购买入口;(2)为WebServiceMediator,使抽象服务持有中介者引用;(3)为abstract void buyService(double money),由具体服务实现。Amazon和Ebay的buyService都把金额与当前对象传给中介者,因此(4)、(5)均为mediator.buy(money, this)。

当前代码的路由是:service等于登记的amazon对象时调用amazon.search,否则调用ebay.search。应按所给代码解释,不改成跨平台互相发送;this用于让中介者识别发起服务。运行前需登记两个服务,并把同一个中介者注入它们,当前题段没有客户端初始化代码。

题面中private WebService ebay:、this.amazon-amazon:、this.mediator = mediator:和system.out.println会导致编译失败,须分别整理为分号、赋值语句及System的正确大小写。仅填五空不能消除这些问题;原页已核实这四处确实如此。Ebay的search方法及类的两个闭括号后即知识点,没有客户端,所给题段完整。上方保留原题代码的写法;补充测试显式创建并连接服务与中介者,客户端属于测试代码。登记为空或传入未登记对象时,原代码没有校验,不能由此认为它已经覆盖真实支付系统的错误处理。

2020-case Q006

在线支付的C++填空

在线支付需要对接不同电子商务平台的接口。希望客户在不同平台购物时,无须关心具体支付接口,因此采用中介者(Mediator)模式整合。图5-1给出类图。

阅读C++代码,填写空(1)~(5)。

Class WebService;  
Class WebServiceMediator{  
public:  
(1) =0;  
Virtual void SetAmazon(WebService *amazon) =0;  
Virtual void SetEbay(WebService *ebay) =0;  
};  
Class WebService{  
Protected:  
(2) mediator;  
public  
virtual void Set ServiceMediator (WebServiceMediator *mediator) = 0;  
(3);  
virtual void search(double money) = 0;  
}  
Class ConcreteSerciceMediator: public WebServiceMediator { // Concrete iator  
Private:  
WebService * amazon;  
WebService * ebay;  
Public:  
ConcreteSerciceMediator(): amazon(NULL),ebay(NULL){ }  
void SetAmazon(WebService *amazon) { this- > amazon = amazon; }  
void SetEbay(WebService *ebay) {  
this- > ebay = ebay;  
}  
void buy(double money,Webservice *service) {  
if (service = = amazon) amazon- > search(money);  
else ebay- > search(money);  
}  
};  
class Amazon: public WebService {  
public:  
void SetMediator(WebServiceMediator *mediator){  
this- > mediator = mediator;  
}  
Void buyService(double money){  
(4);  
}  
void search(double money){  
cout < < ”Amazon receive:”< < money < < endl;  
}  
};  
class Ebay: public WebService{  
public:  
void SetMediator (WebServiceMediator *madiator){  
this - > mediator = mediator  
}  
Void buyService(double money){  
(5);  
}  
Void search(double money){  
Cout < < ”Ebay receive:”< < money < < endl;  
}  
};
答案与解析

平台参考答案(原文保留)

(1) virtual void buy(double money, WebService *service)
(2) WebServiceMediator *
(3) virtual void buyService(double money)= 0
(4) mediator- > buy(money, this)
(5) mediator- > buy(money, this)

解析与纠错

(1)为virtual void buy(double money, WebService *service),题面后面已有=0;(2)为WebServiceMediator *;(3)为virtual void buyService(double money)=0。两个具体服务均用mediator->buy(money, this)把请求交给中介者,因此(4)、(5)的含义相同。平台这两空保留了分开的“- >”,在C++中应写为连续的->。

图中的中介者统一处理购买请求,服务通过中介者接口通信。原buy方法根据指针是否等于已登记amazon,分别调用amazon或ebay的search;参数this传递当前服务的身份。测试必须同时登记两个服务并设置它们的中介者,不能只创建对象就期待调用成功。

原题C++代码有较多不能直接编译的写法:Class、Virtual、Protected、Private、Public、Void等关键字大小写,public缺冒号,WebService类末缺分号,Set ServiceMediator名称与派生类SetMediator不一致,Webservice类型名大小写、分开的运算符、弯引号、Cout大小写及Ebay赋值末尾分号等。ConcreteSerciceMediator在类名与构造器处一致,虽与图中ConcreteServiceMediator拼法不同,不能将两种名字随意混用。缺少头文件和命名空间声明也不能靠五个空解决。原页已核实这些写法均为原文:从Class WebService;开始,没有include或using,最后Ebay的};后即知识点,没有遗漏后续代码。平台第(4)、(5)空也确为mediator- > buy(money, this),原答案保留。

Ebay的形参写成madiator,而赋值右边用mediator;若仅修语法,右边可能引用继承的同名成员,形成自赋值,仍不会保存传入的中介者。这是需要单独纠正的语义问题。学习测试版本明确补充编译依赖、统一接口与标识符、补分号和运算符,并将形参改为mediator;所有整理均与原题代码区分。

2019年下半年软件设计师案例真题:案例题

本节保留 3 条来源,答案与解析默认收起。

2019-11-case Q003

牙科诊所的用例与类图

某牙科诊所拟开发系统管理病人基本信息和就诊信息。工作人员包括医护人员(Dental Staff)、接待员(Receptionist)、办公人员(Office Staff)等,功能如下。

  1. 记录病人基本信息(Maintain patient info):病人初次就诊时由接待员录入姓名、身份证号、出生日期、性别、首次就诊时间、最后一次就诊时间等。每位病人与其医保信息(Medical Insurance)关联。
  2. 记录就诊信息(Record office visit info):每次就诊由接待员录入就诊信息(Office Visit),包括就诊时间、就诊费用、支付代码、病人支付费用、医保支付费用等。
  3. 记录治疗信息(Record dental procedure):一次就诊可能接受多项治疗(Procedure),每项治疗可能由多位医护人员服务。治疗信息包括治疗项目名称、治疗项目描述、治疗的牙齿、费用等,每位参与治疗的医护人员分别录入。
  4. 打印发票(Print invoices):办公人员打印发票(Invoice),分给医保机构的发票(Insurance Invoice)及给病人的发票(Patient Invoice);两种内容相同,仅支付费用不同。收到治疗费用后,由办公人员更新支付状态(Enter payment)。
  5. 记录医护人员信息(Maintain dental staff info):办公人员录入医护人员姓名、职位、身份证号、家庭住址、联系电话等。
  6. 医护人员可查询并打印本人参与的治疗项目相关信息(Search and print procedure info)。

采用面向对象方法,得到图3-1用例图及图3-2初始类图。

【问题1】(6分)依据说明,填写图3-1参与者A1~A3及用例U1~U3的名称。

【问题2】(5分)依据说明,填写图3-2类C1~C5的名称。

【问题3】(4分)依据说明,写出图3-2中C4、C5、Patient、Dental Staff的必要属性。

答案与解析

平台参考答案(原文保留)

【问题1】 A1: Receptionist(接待员) A2: Dental Staff(医护人员) A3: Office Staff(办公人员) U1:Maintain patient info (记录病人基本信息) U2:Record office visit info (记录就诊信息) U3: Print invoices(打印发票) 【问题2】 C1: Patient Invoice C2: Insurance Invoice C3: Invoice C4: Procedure C5:Office Visit 【问题3】 C4:治疗项目名称、治疗项目描述、治疗的牙齿和费用 C5:病人就诊时间和费用、支付代码、病人支付费用、医保支付费用 Patient:姓名、身份证号、出生日期、性别、 首次就诊时间和最后一次就诊时间 Dental Staff:姓名、职位、身份证号、住址、联系电话。

解析与纠错

先按角色职责匹配:A1为接待员,负责U1记录病人基本信息、U2记录就诊信息;A2为医护人员,负责治疗记录及查询打印;A3为办公人员,负责U3打印发票、更新支付状态、维护医护人员信息。图中A3连向U2,但说明没有给办公人员记录就诊信息的职责,平台解析也指出这一额外连线缺乏依据;保留题图,不由该线自行增加权限。

C1、C2的公共父类C3对应发票Invoice;两类分别是Patient Invoice、Insurance Invoice。C4与Dental Staff及一次就诊相连,故为Procedure;C5与病人及治疗相连,为Office Visit。C2端的0..*表示一份医保信息可以暂时没有关联的医保发票,不能仅由这一个端点就推出具体某次就诊必为全自费;平台用全自费作业务解释,需要支付情况支持。初始图中的其他多重度也不能取代文字需求的完整约束。

属性从描述逐项提取:C4为治疗项目名称、治疗项目描述、治疗的牙齿、费用;C5为就诊时间、就诊费用、支付代码、病人支付费用、医保支付费用。Patient为姓名、身份证号、出生日期、性别、首次就诊时间、最后一次就诊时间;Dental Staff为姓名、职位、身份证号、家庭住址、联系电话。一次就诊可含多项治疗、每项治疗可涉及多人,不应把这些多值关系直接压成单个姓名字段。

2019-11-case Q005

文件管理系统的C++填空

文件管理系统定义OfficeDoc和DocExplorer。OfficeDoc发生变化时,DocExplorer的所有对象都要更新自身状态;现用观察者(Observer)模式实现,图5-1为类图。

阅读下列C++代码,填写空(1)~(5)。

#include < iostream >  
#include < vector >  
#include < string >  
Using namespace std;  

Class Observer{  
Public:  
(1);  
};  

Class Subject{

Protected:  
Vector < (2) > myobs;  
public:  
virtual void Attach(Observer*obs) {myobs.push_back(obs);}  
virtual void Detach(Observer*obs) {  
for (vector < observer* >::iterator iter = myobs.begin();iter!=myobs.end(); iter++){  
if(*iter == obs){myobs.erase(iter);return;}  
}  
}  
virtual void Notify(){  
for (vector < observer* >::iterator iter = myobs.begin();iter!=myobs.end(); iter++){  
(3);}  
}  
virtual int getStatus() = 0;  
virtual void setStatus(int status) = 0;  
};  

classOfficeDoc: public Subject{  
private:  
stringmySubjectName;  
intm_status;  
public:  
OfficeDoc(string name): mySubjectName(name), m_status(0){}  
voidsetStatus(int status){m_status = status;}  
intgetStatus(){return m_status;}  
};  

classDocExplorer: public observer{  
private:  
stringmyObsName;  
public:  
DocExplorer(string name, (4) sub):myobsName(name){sub- > (5);}  
Void update(){cout < < “update observer:” < < myObsName < < endl;}  
};  
int main(){  
Subject *subjectA = new OfficeDoc(“subject A”);  
Observer *observerA = new DocExplorer(“observerA”,subjectA);  
subjectA- > setStatus(1);subjectA- > Notify();  
return 0;  
}
答案与解析

平台参考答案(原文保留)

(1)virtual void update()=0
(2)Observer*
(3)(*iter)- > update()
(4)Subject*
(5)Attach(this)

解析与纠错

Observer声明纯虚更新接口,故(1)为virtual void update()=0;Subject的列表保存观察者指针,(2)为Observer*。Notify遍历列表并调用每个对象的更新方法,(3)对应(*iter)->update()。DocExplorer通过抽象目标注册,(4)为Subject*,(5)为Attach(this)。平台答案(3)中的分开箭头“- >”须写成连续->才是C++运算符。

setStatus仅设置状态,真正通知发生在显式调用Notify时,不能理解为赋值自动触发。构造器把this登记到目标中;当前DocExplorer只保存名称,没有保存传入的Subject指针,update也只是打印通知,不包含读取目标状态或刷新文件视图的完整实现。平台解析所说“维护一个指向目标的对象”是常见扩展思路,不是当前代码已经具备的成员。

所给代码还有关键字大小写、头文件名空格、类型名observer、多个声明连写、myObsName/myobsName不一致、弯引号、分开的<<和->等编译问题。学习测试版本会明确修正这些写法,再核对注册、通知、撤销行为;上方原题不将修正混入。原页已核实这些连写、大小写及名称差异均为原文;DocExplorer确实只有名称成员。题面含main,最后return 0;及闭括号后即知识点,没有遗漏的声明或后续代码。平台答案(3)的分开箭头也已核实。

2019-11-case Q006

文件管理系统的Java填空

文件管理系统定义OfficeDoe和DocExplorer。OfficeDoe发生变化时,DocExplorer的所有对象都要更新自身状态;现用观察者(Observer)模式实现,图6-1为类图。

阅读下列Java代码,填写空(1)~(5)。

import java.util.*;  
interface Observer{  
public (1);  
}  

interface Subject{  
public void Attach(Observer obs);  
public void Detach(Observer obs);  
public void Notify();  
public void setStatus(int status);  
public int getStatus();  
}  

class OfficeDoc implements Subject{  
private List < (2) > myObs;  
private String mySubjectName;  
private int m_status;  
public OfficeDoc(String name){  
mySubjectName=name;  
this.myObs=new ArrayList < Observer > ();  
m_status=0;  
}  
public void Attach(Observer obs){this.myObs.add(obs);}  
public void Detach(Observer obs){this.myObs.remove(obs);}  
public void Notify(){  
for(Observer obs:this.myObs){  
(3);  
}  
}  
public void setStatus(int status){  
m_status=status;  
System.out.println("SetStatus subject["+mySubjectName+"]status:"+status);  
}  
public int getStatus(){return m_status;}  
}  

class DocExplorer implements Observer{  
private String myObsName;  
public DocExplorer(String name, (4) sub){  
myObsName=name;  
sub. (5);  
}  
public void update(){  
System.out.println("update observer["+myObsName+"]");  
}  
}  

class ObserverTest{  
public static void main(String []args) {  
System.out.println("Hello World!");  
Subject subjectA=new OfficeDoc("subject A");  
Observer oberverA=new DocExplorer("observer A",subjectA);  
subjectA.setStatus(1);  
subjectA.Notify();  
}  
}
答案与解析

平台参考答案(原文保留)

(1)void update()
(2)Observer
(3)obs.update()
(4)Subject
(5)Attach(this)

解析与纠错

(1)为void update(),是Observer接口的更新操作;(2)为Observer,限定列表元素类型。Notify中的obs是增强for循环的当前元素,因此(3)为obs.update();平台解析把它称作Notify传入的参数并不准确,该方法本身没有参数。

DocExplorer接收抽象目标Subject,所以(4)填Subject;调用sub.Attach(this)把当前对象加入通知列表,所以(5)填Attach(this)。setStatus改变状态并打印消息,随后main显式调用Notify才会通知观察者;DocExplorer.update仅打印通知文字,没有进一步复制目标状态。

五空代入后,示例输出应为:

1
2
3
Hello World!
SetStatus subject[subject A]status:1
update observer[observer A]

原页已核实说明两处均为OfficeDoe,类图与Java代码为OfficeDoc;说明和代码均保留原写法。main局部变量oberverA虽少一个s,但前后没有错误引用,不影响这段程序编译。

2019年上半年软件设计师案例真题:案例题

本节保留 3 条来源,答案与解析默认收起。

2019-05-case Q003

书籍销售系统的用例与类图

图书公司计划开发Web书籍销售系统,供顾客(Customer)在线购买书籍(Books),并管理库存和销售。功能要求如下。

  1. 首次使用时注册(Registerdetail):顾客填写姓名name、收货地址address、电子邮箱email等,系统生成注册码。
  2. 注册成功后可登录并购买书籍(Buybooks),浏览书名title、作者author、内容简介introduction等。库存量为0的书籍无法查询。顾客选择书籍和购买数量quantities;超过库存量时提示库存不足,小于库存量时显示验证界面,要求输入注册码。验证正确则自动生成订单Order,否则提示验证错误;顾客可按需打印订单(Printorder)。
  3. 派送人员(Dispatcher)每天早晨从系统获取当日派送列表(Producepicklist),按收货地址派送书籍。
  4. 采购人员(Buyer)负责采购(Reorderbooks),每天查询库存量低于再次订购量的书籍并补货;新书到货时,向在线销售目录Catalog添加书籍信息(Addbooks)。
  5. 采购人员按销售情况,为销量较低的书籍设置折扣或促销(Promotebooks)。
  6. 新书到货时,仓库管理员(Warehouseman)接收书籍并更新库存(Updatestock)。

图3-1为用例图,图3-2为初始类图的一部分。

【问题1】(6分)填写图3-1参与者A1~A3及用例U1~U3的名称。

【问题2】(6分)根据说明为U3编写用例描述,必须包括基本事件流和所有备选事件流。

【问题3】(3分)填写图3-2中C1~C3的类名。

答案与解析

平台参考答案(原文保留)

【问题1】(6分) A1:采购人员或Buyer A2:仓库管理员Warehouseman A3:派送人员或Dispatcher U1:注册或Registerdetail U2:打印订单或 Printorder U3:购买书籍或Buybooks 【问题2】 U3用例描述 参与者顾客。 主要事件流: 1、顾客登录系统; 2、顾客浏览书籍信息; 3、系统检查某种书籍的库存量是否为0; 4、顾客选择所需购买的书籍及购买数量; 5、系统检查库存量是否足够; 6、系统显示验证界面; 7、顾客输入验证码验证; 8、系统自动生成订单; 备选事件流: 3a. 若库存量为0则无法查询到该书籍信息,退回到2; 5a. 若购买数量超过库存量,则提示库存不足,并退回到4; 7a. 若验证错误,则提示验证错误,并退回到6; 8a. 若顾客需要可以选择打印订单。 前置条件: 1、注册成功。 后置条件: 1、购买成功 【问题3】 C1:顾客或Customer C2:订单或Order C3:书籍或Books

解析与纠错

A1采购人员Buyer负责补货、促销和添加书籍,A2仓库管理员Warehouseman负责更新库存,A3派送人员Dispatcher获取派送列表。顾客独立的U1是注册Registerdetail;图中extend箭头由U2指向U3,故U2为可选的打印订单Printorder,U3为购买书籍Buybooks。

U3的参与者为顾客,前置条件是注册成功。基本事件流可写:顾客登录并浏览可售书籍,选择书籍与数量;系统检查数量符合题设“小于库存量”条件后显示验证界面;顾客输入注册码,验证成功后系统生成订单,购买流程成功结束。

备选流需要覆盖四种情况:库存为0,书籍不显示,继续浏览其他书;购买量超过库存,提示不足并重新选择数量;注册码错误,提示错误并返回验证界面;订单生成后,顾客可选择打印。参考答案称“验证码”,应按题意理解为注册时生成的注册码,不能另发明短信校验流程。

原页已核实说明只写“大于”和“小于”库存量,未另述购买数量恰好等于库存量的处理;题干保留严格小于。实际系统通常允许等于库存,但那是需求补全,不是原题已明确的分支。

C1含name/address/email,为Customer;C3含title/author/introduction,为Books;C2聚合OrderedBook订单项,故为Order。OrderedBook的quantity是每项购买量,不能与书籍总库存混为一项属性。

2019-05-case Q005

竞速游戏的Java填空

某软件公司开发汽车竞速游戏,需要模拟长轮胎、短轮胎急刹车在路面留下的不同痕迹,并考虑后续扩展更多轮胎。采用策略(Strategy)模式,图5-1给出类图。

阅读Java代码,填写空(1)~(5)。

import java.util.*;  
interface BrakeBehavior {  
public (1);  
/* 其余代码省略 */  
};  
class LongWheelBrake implements BrakeBehavior {  
public void stop() { System.out.println("模拟长轮胎刹车痕迹! "); }  
/* 其余代码省略 */  
};  

class ShortWheelBrake implements BrakeBehavior {  
public void stop() { System.out.println("模拟短轮胎刹车痕迹! "); }  
/* 其余代码省略 */  
};  
abstract class Car {  
protected (2) wheel;  
public void brake() { (3); }  
/* 其余代码省略 */  
}:  
class ShortWheelCar extends Car {  
public ShortWheelCar(BrakeBehavior behavior) {  
(4);  
}  
/* 其余代码省略 */  
};  
class StrategyTest{  
public static void main(String[] args) {  
BrakeBehavior brake = new ShortWheelBrake();  
ShortWheelCar car1 = new ShortWheelCar(brake);  
car1. (5);  
}  
}
答案与解析

平台参考答案(原文保留)

(1)void stop()
(2)BrakeBehavior
(3)wheel.stop()
(4)wheel=behavior
(5)brake()

解析与纠错

BrakeBehavior约定统一刹车操作,(1)为void stop()。Car持有策略引用,所以(2)为BrakeBehavior,(3)用wheel.stop()委托调用。(4)把传入策略保存到继承来的wheel字段,即wheel=behavior;(5)通过车辆的brake()入口执行,示例会输出短轮胎刹车痕迹。

替换传入的BrakeBehavior实现即可改变行为,新增策略也不必修改Car.brake的委托逻辑。构造器中behavior是参数、wheel是被赋值的成员,平台“对参数wheel赋值”的说法不准确。原题没有策略setter,不能称其已经提供运行期间切换接口。

题图在BrakeBehavior下面把具体策略标成LongWheelCar、ShortWheelCar,与代码中的LongWheelBrake、ShortWheelBrake及上方车辆继承层次混淆;学习时应将下面两类理解为具体刹车策略,原图保留。Car结束处的}:会造成Java语法错误,整理版仅将冒号去掉。原页已核实Car确以}:结束,“其余代码省略”均为题面明示,五空与StrategyTest.main完整,末尾两个闭括号后即知识点。保留这些省略标记,不将其判为提取缺失。

2019-05-case Q006

竞速游戏的C++填空

某软件公司开发汽车竞速游戏,需要模拟长轮胎、短轮胎急刹车在路面留下的不同痕迹,并考虑后续扩展更多轮胎。采用策略(Strategy)模式,图6-1给出类图。

阅读C++代码,填写空(1)~(5)。

#include < iostream >  
using namespace std;  
class BrakeBehavior {  
public:  
(1);  
/* 其余代码省略 */  
};  
class LongWheelBrake:public BrakeBehavior {  
public:  
void stop() { cout < < "模拟长轮胎刹车痕迹! " < < endl; }  
/* 其余代码省略 */  
};  
class ShortWheelBrake: public BrakeBehavior {  
public:  
void stop() { cout < < "模拟短轮胎刹车痕迹! " < < endl; }  
/* 其余代码省略 */  
};  
class Car {  
protected:  
(2) wheel;  
public:  
void brake() { (3); }  
/* 其余代码省略 */  
};  
class ShortWheelCar: public Car {  
public:  
ShortWheelCar(BrakeBehavior* behavior) {  
(4);  
}  
/* 其余代码省略 */  
};  
int main() {  
BrakeBehavior* brake = new ShortWheelBrake();  
ShortWheelCar car1(brake):  
car1. (5);  
return 0;  
}
答案与解析

平台参考答案(原文保留)

(1)virtual void stop()=0
(2)BrakeBehavior*
(3)wheel- > stop()
(4)wheel=behavior
(5)brake()

解析与纠错

抽象策略接口用纯虚函数,故(1)为virtual void stop()=0;车辆保存策略指针,(2)为BrakeBehavior*,(3)通过wheel->stop()调用动态绑定的具体刹车操作。(4)为wheel=behavior,(5)为brake()。原参考答案的“- >”保留,但C++运算符须写成连续->。

ShortWheelCar的构造器接收抽象策略,因此行为取决于传入对象;长、短轮胎及新增策略都可通过同一接口使用。wheel是成员而不是构造参数;原代码没有运行时更换策略的方法。图中BrakeBehavior下的两个类误标为汽车类,与代码的LongWheelBrake、ShortWheelBrake不一致,纠正名称只在解析中说明。

所给代码还有头文件名空格、继承处全角冒号、分开的流运算符,以及ShortWheelCar car1(brake):结尾冒号等编译问题。测试版会明确修正这些标点后核对调用结果,不把修正版当原题。main以new创建策略却没有释放;补充测试采用有效生命周期的栈对象验证多态,原代码本身没有说明对象所有权。原页已核实上述标点与平台分开箭头均如此,各处“其余代码省略”为题面明示,main至return 0;及闭括号完整结束后即知识点,没有遗漏后续代码。

2018年下半年软件设计师案例真题:案例题

本节保留 3 条来源,答案与解析默认收起。

2018-11-case Q003

SNS群组的类图设计

社交网络平台SNS支持在线群组,成员可互相分享或挖掘兴趣和活动。群组记录标题、管理员、成员列表等。

用户可自行加入或退出群组。每个群组有一个主页,所有成员都可查看;主页发布或更新信息时,组内成员会自动收到相应信息。退出后不再接收该群组的任何发布或更新信息。

采用面向对象方法得到表3-1类列表及图3-1类图,二者在下图中。

【问题1】(6分)根据说明填写图3-1中C1~C3的类名。

【问题2】(6分)指出图3-1采用的设计模式,并说明其意图和适用场合。

【问题3】(3分)新增需求:一个群体可成为另一群体的成员,例如群体A加入B后,A中的所有成员自动成为B的成员。用文字说明图3-1需要怎样修改。

答案与解析

平台参考答案(原文保留)

【问题1】
C1:SNSGroup;C2:SNSUser;C3:SNSAdmin。
(其中C2、C3可以互换)
【问题2】
采用的设计模式:观察者模式
意图:定义对象间的 一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。
适用场合:
(1)当一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两者封装在独立的对象中以使它们可以各自独立地改变和复用。
(2)当对一个对象的改变需要同时改变其他对象,而不知道具体有多少对象有待改变时。
(3)当一个对象必须通知其他对象,而它又不能假定其他对象是谁,即不希望这些对象是紧耦合的。
【问题3】
(1)在SNSSubject和SNSObserver之间增加继承关系,SNSObserver为基类,SNSSubject为派生类。
(2)为类SNSGroup增加自关联(自己到自己的关联关系)。

解析与纠错

SNSSubject提供AddUser、RemoveUser、Notify,是被观察目标的抽象;发布群组主页内容的具体目标C1为SNSGroup。SNSObserver声明Update,具体关注者为SNSUser和SNSAdmin,对应C2、C3,两者位置可互换。

采用观察者模式:一个目标状态变化时,通知已登记的多个观察者,目标只依赖统一接口。适用于目标与显示/关注方应分别变化、观察者数量动态变化,或通知方不应依赖具体接收者的场景。加入群组对应注册,退出对应撤销,不能只在界面移除成员却仍保留通知登记。

按平台对嵌套群组的修改:让SNSSubject继承SNSObserver,使群组既能作为通知源,也能作为其他群组的观察者;SNSGroup再增加自关联表达群组成员关系。A加入B时可把A登记为B的观察者,A收到更新后向本组成员转发。仅画继承和自关联并不会自动实现传播,更新操作仍需承担这一逻辑;实现时还应明确重复成员和循环嵌套的处理。这些是对图意的说明,不替换原参考答案。

2018-11-case Q005

航空会员积分的C++填空

某航空公司会员积分系统分普卡Basic、银卡Silver、金卡Gold三个等级;非会员Non Member可申请成为普卡。等级按一年内累积的里程数调整。图5-1给出调整状态图,图5-2是采用状态State模式设计的类图。

阅读C++代码,填写空(1)~(5)。

#include < iostream >  
using namespace std;  
class FrequentFlyer; class Cbasic; class Csilver; class Cgold; class CnoCustomer; // 提前引用  
//提前引用  
class CState {  
private: int flyMiles; // 里程数  
public:  
(1) ; // 根据累积里程数调整会员等级  
};  
class FrequentFlyer {  
friend class Cbasic; friend class Csilver; friend class Cgold;  
private:  
Cstate *state; Cstate *nocustomer; Cstate *basic; Cstate *silver; Cstate *gold;  
double flyMiles;  
public:  
CFrequentFlyer(){ flyMiles = 0; setState(nocustomer); }  
void setState(CState *state){ this- > state = state; }  
void travel(int miles) {  
double bonusMiles = state- > travel(miles,this);  
flyMiles = flyMiles + bonusMiles;  
}  
};  
class CnoCustomer: public CState { // 非会员  
public:  
double travel(int miles, FrequentFlyer* context) { // 不累积里程数  
cout < < “Your travel will not account for points\n”; return miles;  
}  
};  
class CBasic: public CState { // 普卡会员  
public:  
double travel(int miles, FrequentFlyer* context) {  
if(context- > flyMiles > = 25000 && context- > flyMiles < 50000)  
(2) ;  
if(context- > flyMiles > =50000) (3) ;  
return miles + 0.5*miles; // 累积里程数  
}  
};  
class CGold: public CState { // 金卡会员  
public:  
double travel(int miles, FrequentFlyer* context) {  
if(context- > flyMiles > = 25000 && context- > flyMiles < 50000)  
(4) ;  
if(context- > flyMiles < 25000) (5) ;  
return miles + 0.5*miles; // 累积里程数  
}  
};  
class Csilver: public CState { // 银卡会员  
public:  
double travel(int miles, FrequentFlyer* context) {  
if(context- > flyMiles < 25000)  
context- > setState(context- > basic);  
if(context- > flyMiles > = 50000)  
context- > setState(context- > gold);  
return(miles + 0.25*miles);  
}  
};
答案与解析

平台参考答案(原文保留)

(1)virtual double travel(int miles,FrequentFlyer* context)=0
(2)context- > setState(context→silver)

(3)context- > setState(context→gold)

(4)context- > setState(context→silver)

(5)context- > setState(context→basic)

解析与纠错

(1)为virtual double travel(int miles,FrequentFlyer* context)=0。按图,25000≤里程<50000进入银卡,里程≥50000进入金卡,低于25000回到普卡;因此(2)、(3)、(4)、(5)依次设置silver、gold、silver、basic。平台原答案中的Unicode箭头和分开的“- >”保留,C++调用需使用->;长解析的“<5000”与“ncontext”都是错误,阈值应为50000,接收对象应为context。

仅填空后的代码不能直接编译:CState/Cstate、CBasic/Cbasic、CGold/Cgold大小写不一致;FrequentFlyer内却写CFrequentFlyer构造名;头文件空格、弯引号、全角分号及分开的操作符也有问题。C++纯虚函数使用virtual与=0,并没有这里可直接使用的abstract关键字。

更重要的是,nocustomer/basic/silver/gold指针没有可见的对象创建或初始化,构造时就把未初始化nocustomer传给setState,后续调用不安全。原页已核实没有状态对象创建或指针初始化,Csilver末尾};后即知识点,没有main、注册或年度清零后续;来源完整,原实现仍有缺陷。测试只在明确标注的补充装配代码中传入实际状态对象,不把这些补全作为原题。

按这段C++原逻辑,普卡与金卡都返回1.5倍里程,银卡为1.25倍;题图没有规定奖励倍率,不能擅自把普卡改成Java题中的1倍。非会员返回miles,而上下文又累加它,因此会实际累计里程,与“不累积”注释冲突。状态判断使用本次飞行前的总里程,跨越阈值后通常要等下一次travel才调整;同一次调用仍返回进入方法时的等级倍率。题面也没有实现申请会员和一年内里程的更新规则,不能宣称已覆盖完整会员业务。

2018-11-case Q006

航空会员积分的Java填空

某航空公司会员积分系统分普卡Basic、银卡Silver、金卡Gold三个等级;非会员Non Member可申请成为普卡。等级按一年内累积的里程数调整。图6-1给出调整状态图,图6-2是采用状态State模式设计的类图。

阅读Java代码,填写空(1)~(5)。

import java.util.*;  

abstract class CState {  
public int flyMiles; // 里程数  
public (1) ; // 根据累积里程数调整会员等级  
}  
class CNoCustomer extends CState { // 非会员  
public double travel(int miles, FrequentFlyer context) {  
System.out.println ( “Your travel will not account for points”);  
return miles; // 不累积里程数  
}  
}  
class CBasic extends CState { // 普卡会员  
public double travel(int miles, FrequentFlyer context) {  
if(context.flyMiles >= 25000 && context.flyMiles < 50000)  
(2) ;  
if(context.flyMiles >= 50000)  
(3) ;  
return miles;  
}  
}  
class CGold extends CState { // 金卡会员  
public double travel(int miles, FrequentFlyer context) {  
if(context.flyMiles >= 25000 && context.flyMiles < 50000)  
(4) ;  
if(context.flyMiles < 25000)  
(5) ;  
return miles + 0.5*miles; // 累积里程数  
}  
}  
class CSilver extends CState { // 银卡会员  
public double travel(int miles, FrequentFlyer context) {  
if(context.flyMiles <= 25000)  
context.setState(new Cbasic());  
if(context.flyMiles >= 50000)  
context.setState(new Cgold());  
return (miles + 0.25*miles); // 累积里程数  
}  
}  
class FrequentFlyer {  
CState state;  
double flyMiles;  
public FrequentFlyer(){  
state = new CnoCustomer();  
flyMiles = 0;  
setState(state);  
}  
public void setState(CState state){ this.state = state; }  
public void travel(int miles) {  
double bonusMiles = state.travel(miles,this);  
flyMiles = flyMiles + bonusMiles;  
}  
}
答案与解析

平台参考答案(原文保留)

(1)abstract double travel(int miles,FrequentFlyer context)

(2)context.setState(new CSilver())

(3)context.setState(new CGold ())

(4)context.setState(new CSilver())

(5)context.setState(new CBasic())

解析与纠错

(1)补abstract double travel(int miles,FrequentFlyer context)。按状态图,(2)创建CSilver,(3)创建CGold,(4)创建CSilver,(5)创建CBasic,并分别调用context.setState。平台解析把银卡上限写成5000,正确上限为50000。

银卡代码却在flyMiles<=25000时降普卡,和图中严格小于25000不一致。恰为25000时,从银卡调用travel(0)会变普卡,再调用一次又变银卡;若按图整理,这一处应为<25000。原页已核实这里确含等号,题干保留原写法。

CNoCustomer、CBasic、CGold的声明与new CnoCustomer()/Cbasic()/Cgold()不一致,Java区分大小写;弯引号、全角分号也需明确修正后才能编译。非会员方法返回miles,上下文照样累加,与“不累积里程数”注释冲突。普卡1倍、银卡1.25倍、金卡1.5倍是本段代码行为,不可按另一语言题改动原文。

本次里程在状态方法返回后才累加,故按飞行前总里程判断会使跨阈值的升级滞后;题面未提供注册为普卡、维护一年内累计值等完整业务流程。测试分别保留这些行为来核对问题,不用静默修正来冒充原程序正确。原页已核实类名大小写、弯引号、全角分号、非会员与普卡返回miles均如此。travel累加flyMiles后两个闭括号直接结束,没有额外代码;来源完整。

2018年上半年软件设计师案例真题:案例题

本节保留 3 条来源,答案与解析默认收起。

2018-05-case Q003

ETC收费系统的用例与类图

某ETC(ElectronicTollCollection,不停车收费)系统在高速公路特定位置设置龙门架(Tollgantry)。每个龙门架下有6条车道(Trafficlanes),每条车道装有雷达传感器(Radarsensor)、无线传输器(Radiotransceiver)、数码相机(DigitalCamera)等设备,使车辆以正常速度行驶时完成收费。业务过程如下。

  1. 汽车安装车载器,驾驶员(Driver)插入具有唯一识别码的磁卡,卡内保存驾驶员账户当前信用记录。
  2. 车辆经过车道时,设备识别车载器特有编码、判断车型,将信息发往该路段所属区域系统(Regionalcenter)。区域系统计算通行费、创建收费交易(Transaction),从驾驶员专用账户扣款;透支时记录透支账户交易,再将交易后账户信息发给维护账户的中心系统(Centralsystem)。
  3. 车载磁卡可在邮局付款机充值;充值信息传至中心系统,更新驾驶员账户余额。
  4. 无车载器或车载器故障时,数码相机拍照,将照片及拍摄时间发至区域系统,记录失败交易,再将该交易信息发至中心系统。
  5. 区域系统获取收费设备记录的交通事件(Trafficevents);交通广播电台(Trafficadvicecenter)据此分析并播报路况。

采用面向对象方法得到表3-1用例列表、图3-1用例图与图3-2分析类图。

【问题1】(4分)写出图3-1中A1~A4对应的参与者名称。

【问题2】(5分)结合说明和表3-1,写出图3-1中U1~U5对应的用例名称。

【问题3】(6分)写出图3-2中C1~C6对应的类名。

答案与解析

平台参考答案(原文保留)

【问题1】 A1: Central system或中心系统 A2: Driver 或驾驶员 A3: Regional center 或区域系统 A4: Traffic advice center 或交通广播电台 其中A1、A2可以互换;A3、A4可以互换。 【问题2】 U1: Underpaid transaction U2: Record Illegal use U3: Create transaction U4: Record traffic event U5: Charge card 其中U1、U2可以互换,用例名称必须为英文,因为表中的汉字是对用例的说明。 【问题3】 C1: Central system C2: Toll gantry C3: Traffic lanes C4: Radar sensor C5: Radio transceiver C6: Digital Camera 其中C4、C5、C6可以互换。

解析与纠错

U3是正常创建收费交易,U1/U2是在透支、无法识别车载器等特殊条件下记录异常,因此是指向U3的extend;二者可互换。独立的U4记录交通事件,与区域系统和交通广播电台关联;U5磁卡充值与驾驶员、中心系统关联。相应A1/A2与A3/A4分别可以互换,平台提供的英文用例名全部保留。

类图按“中心系统—区域系统—龙门架—6条车道—三种设备”定位:C1为Central system,C2为Toll gantry,C3为Traffic lanes;C4~C6为Radar sensor、Radio transceiver、Digital Camera,三种设备的空位可互换。C3与Transaction关联,也支持C3是实际进行交易的车道。

平台解析称“C4、C5、C6与C3组合,对应龙门架”不准确:三种设备组成的是车道,龙门架组合6条车道。图3-2在Regional Center—C2连线的Regional Center端标*,不能反过来当作C2端的多重性;若要表达一个区域系统对应多个龙门架,多重性应标在龙门架端。原图和答案均保留,按类名和业务层次区分,不将解析中的口误带入填空。

2018-05-case Q005

产品构建的C++填空

生成器(Builder)模式将复杂对象的构建过程与表示分离,使同一构建过程可以创建不同表示。图5-1给出其类图。

阅读下列C++代码,填写空(1)~(5)。

#include < iostream >

#include < string >

using namespace std;

class Product {

private:

string partA, partB;

public:

Product() { }

void setPartA(const string& s) { PartA = s;}

void setPartB(const string& s) { PartB = s;}

// 其余代码省略

};

class Builder {

public:

(1)

;

virtual void buildPartB()=0;

(2)

;

};

class ConcreteBuilder1: public Builder {

private:

Product* product;

public:

ConcreteBuilder1() {product = new Product(); }

void buildPartA() {

(3)

("Component A"); }

void buildPartB() {

(4)

("Component B"); }

Product* getResult() { return product; }

// 其余代码省略

};

class ConcreteBuilder2: public Builder {

/* 代码省略 */

};

class Director {

private:

Builder* builder;

public:

Director(Builder* pBuilder) { builder= pBuilder;}

void construct() {

(5)

;

// 其余代码省略

}

// 其余代码省略

};

int main() {

Director* director1 = new Director(new ConcreteBuilder1());

director1- > construct();

delete director1;

return 0;

}
答案与解析

平台参考答案(原文保留)

(1)virtual void buildPartA() = 0
(2)virtual Product * getResult() = 0
(3)product- > setPartA
(4)product- > setPartB
(5)builder- > buildPartA();
或builder- > buildPartB();

解析与纠错

Builder需声明构建A部件及取产品接口,所以(1)为virtual void buildPartA()=0,(2)为virtual Product* getResult()=0;两条声明在类内可互换顺序。(3)/(4)分别通过product调用setPartA/setPartB。

(5)由Director委托Builder执行构建步骤。其后明确省略其他代码,单凭可见片段不能限定步骤顺序或认定全部产品已构造完;平台接受调用buildPartA或buildPartB均应保留。若需要A、B齐全,应明确执行这两个步骤。平台第(5)项答案自带分号,题干空后又有分号,填入会多一个空语句,在C++中合法。

原文声明partA、partB,setter却赋给PartA、PartB,C++区分大小写;头文件内空格及分开的“- >”也需明确修正,不能把原填空代码说成可直接编译。原页已核实成员大小写、头文件空格及分开箭头均如此;两个位置明确省略其他代码。main以delete director1、return 0及闭括号结束后即知识点,没有其他成员或释放实现,来源完整。ConcreteBuilder2的实现已明示省略;C++中未实现纯虚函数会保留为抽象类,只要不实例化它,并不因此使整个文件非法。

所示new对象涉及Director、Builder、Product,原文没有展示完整的所有权及释放方式;不能只凭delete director1推断另两个对象也已释放。学习测试在明确的装配中保存、检查和释放对象,不把补充代码当原题。平台长解析误称本题为JAVA,应为C++;Builder强调构建步骤与表示分离,也不等于把任意复杂类构造简单延后到子类。

2018-05-case Q006

产品构建的Java填空

生成器(Builder)模式将复杂对象的构建过程与表示分离,使同一构建过程可以创建不同表示。图6-1给出其类图。

阅读下列Java代码,填写空(1)~(5)。

import java.util.*;

class Product {

private String partA;

private String partB;

public Product() {}

public void setPartA(String s) { partA = s; }

public void setPartB(String s) { partB = s; }

}

interface Builder {

public

(1)

;

public void buildPartB();

public

(2)

;

}

class ConcreteBuilder1 implements Builder {

private Product product;

public ConcreteBuilder1() { product = new Product(); }

public void buildPartA() {

(3)

("Component A"); }

public void buildPartB() {

(4)

("Component B"); }

public Product getResult() { return product;}

}

class ConcreteBuilder2 implements Builder {

// 代码省略

}

class Director {

private Builder builder;

public Director(Builder builder) {this.builder = builder; }

public void construct() {

(5)

;

// 代码省略

}

}

class Test {

public static void main(String[] args) {

Director director1 = new Director(new ConcreteBuilder1());

director1.construct();

}

}
答案与解析

平台参考答案(原文保留)

(1)void buildPartA()

(2)Product getResult()

(3)product.setPartA

(4)product.setPartB

(5)builder.buildPartA()或者 builder.buildPartB()

解析与纠错

(1)补void buildPartA(),(2)补Product getResult();Java接口中的这两条方法声明可互换顺序。(3)/(4)分别为product.setPartA和product.setPartB。Director持有Builder接口,具体构建器负责配置并返回Product,这样相同的构建步骤可以配合不同具体构建器。

(5)后有明示“代码省略”,平台接受builder.buildPartA()或builder.buildPartB()。现有可见片段只能证明调用了所填的那一步,不能据此说A和B一定都已设置;补充测试分别验证两种允许答案,再用明确补全的步骤序列验证完整产品。

原题的ConcreteBuilder2是非abstract类,却只保留省略注释,没有实现接口方法,照抄全部片段会编译失败。这是明示省略与可编译性问题,不能据此认定提取缺行;原页已核实Product、Builder、ConcreteBuilder½、Director、Test齐全,ConcreteBuilder2确为非abstract且仅省略注释;main中director1.construct();及两个闭括号后直接知识点,来源完整。测试版明确将该占位类标为abstract,因题中实际创建的是ConcreteBuilder1,不更改其构建行为。全部补全与测试方法仅用于验证,不冒充原题源码。

2017年下半年软件设计师案例真题:案例题

本节保留 3 条来源,答案与解析默认收起。

2017-11-case Q003

学术出版物的类图设计

某大学拟开发数字图书馆,供用户查询、下载已发表的学术出版物(Publication)。系统需求如下。

  1. 用户(User)仅限本校学生(Student)、教师(Faculty)及其他工作人员(Staff);访问前必须使用校园账户、密码登录。
  2. 可按作者(Author)查询全部出版物。系统保存会议文章(Conf Paper)、期刊文章(JournalArticle)、校内技术报告(TechReport)的题目、作者、出版年份。会议文章还记录会议名称、召开时间、召开地点;期刊文章记录期刊名称、出版月份、期号、主办单位;校内技术报告记录学校分配的唯一ID。
  3. 可查询指定会议集(Proceedings)或期刊某一期(Edition)的全部文章。会议集包含特定时间段、特定地点召开的会议所发表的全部文章;期刊每一期在特定时间发行,包含若干文章。
  4. 用户可下载出版物,系统记录每个出版物的下载次数。
  5. 可查询引用某篇出版物的所有出版物。出版物可引用他人或早期文献作为相关工作、背景资料;用户可为某篇出版物注册引用通知,有新出版物引用它时,系统以电子邮件通知该用户。

采用面向对象方法得到图3-1初始设计类图。

【问题1】(9分)填写图3-1中C1~C9的类名。

【问题2】(4分)写出C6~C9的属性。

【问题3】(2分)指出图中设计模式,以及它实现的系统功能。

答案与解析

平台参考答案(原文保留)

【问题1】
C1:Person
C2:User
C3:Student
C4:Faculty
C5:Staff
C6:Publication
C7:ConfPaper
C8:JournalArticle
C9:TechReport
注:C3/C4/C5可互换。
【问题2】
C6:题目,作者,出版年份
C7:会议名称,召开时间,召开地点
C8:期刊名称,出版月份,期号,主办单位
C9:ID
【问题3】
观察者模式,实现:引用他人学术出版物发送电子邮件通知该用户。

解析与纠错

C2有三种校园用户子类,所以为User,C3~C5是Student、Faculty、Staff,可互换。C2和Author共用的C1可抽象为Person;题干没有给这个父类名称,Person是合理抽象,不是题面明确提供的单词。C6为Publication,C7/C8/C9依次为ConfPaper、JournalArticle、TechReport。

C7连接Proceedings,C8连接Edition,已限制它们分别为会议文章、期刊文章;平台长解析称C7~C9“次序也可随意”不适用于这张带关联的原图。仅C3~C5没有相应区分关联,可以按平台说明互换。

C6保存题目、作者、出版年份;C7补会议名称、召开时间、地点,C8补期刊名称、出版月份、期号、主办单位,C9补ID。子类继承共有信息,不必把共同属性再视为各自独有字段。下载次数也是说明中的持久信息,平台属性答案未列;若覆盖完整需求,可在Publication补下载次数。作者也可由关联表达,而不必重复存为不受约束的文本。

意图是观察者模式:用户注册对某出版物的关注,新引用出现后通知该用户。原图却把Publication画为Observer子类,没有画出User与Subject/Observer的完整登记及通知关系,且Subject—Observer端写0..1,不能单靠这些线就宣称已满足多个用户订阅。常见实现可让出版物或引用管理服务作被观察目标,已登记的用户或通知对象作观察者;此为整理建模建议,原图与平台模式答案保留。

2017-11-case Q005

跨平台图像预览的C++填空

图像预览程序需查看BMP、JPEG、GIF三种格式,并能运行于Windows和Linux。为方便扩展新的文件格式、操作系统并减少所需子类数量,采用桥接(Bridge)模式,类图如图5-1。

阅读C++代码,填写空(1)~(5)。

#include <iostream>

#include <string>

using namespace std;

class Matrix{ // 各种格式的文件最终都被转化为像素矩阵

// 此处代码省略

};

class Implementor{

public:

______(1)______; // 显示像素矩阵 m

};

class WinImp: public Implementor{

public:

void doPaint(Matrix m) { /*调用 Windows 系统的绘制函数绘制像素矩阵*/ }

};

class LinuxImp: public Implementor{

public:

void doPaint(Matrix m) { /*调用 Linux 系统的绘制函数绘制像素矩阵*/ }

};

class Image {

public:

void setImp(Implementor *imp) { this->imp = imp; }

virtual void parseFile(string fileName) = 0;

protected:

Implementor *imp;

};

class BMPImage: public Image{

//此处代码省略

};

class GIFImage: public Image{

public:

void parseFile(string fileName){

// 此处解析 GIF 文件并获得一个像素矩阵对象 m

______(2)______; // 显示像素矩阵 m

}

};

class JPEGImage: public Image{

// 此处代码省略

};

int main() {

// 在 Linux 操作系统上查看 demo.gif 图像文件

Image *image = ______(3)______;

Implementor *imageImp = ______(4)______;

______(5)______;

image->parseFile("demo.gif");

return 0;

}
答案与解析

平台参考答案(原文保留)

(1)virtual void doPaint(Matrix m) = 0
(2)imp- > doPaint(m)

(3)new GIFImage()
(4)new LinuxImp()
(5)image- > setImp(imageImp)

解析与纠错

图像格式与绘制平台是两个可分别扩展的维度:Image及其子类负责解析,Implementor及其子类负责绘制。Image持有Implementor,不需要为每种“格式×系统”组合各写一个类。

(1)声明virtual void doPaint(Matrix m)=0;(2)经imp委托绘制m;(3)创建GIFImage,(4)创建LinuxImp,(5)用setImp把后者注入前者,随后parseFile("demo.gif")即可按意图调用Linux绘制接口。平台分开的“- >”保留,实际C++需合并为->。

可见代码只有“解析GIF文件并获得矩阵m”的注释,没有m的声明或解析实现;不能把填空后的片段当作完整图像解析程序。BMPImage、JPEGImage的实现也明示省略,在C++中它们可仍是抽象类,未实例化不妨碍其余部分编译。原页已核实这里只用注释描述矩阵解析,没有m声明;Matrix、BMPImage、JPEGImage明示省略,main完整结束后即知识点,来源完整。

测试版仅补一个明确标识的矩阵样本,验证setImp与doPaint的委托链、替换平台和扩展格式,不宣称实现了真实GIF解码。原图的组合关系强调所有权,但所示裸指针setter未定义完整生命周期策略;测试装配独立管理对象,不能把它的清理代码算作原题实现。

2017-11-case Q006

跨平台图像预览的Java填空

图像预览程序需查看BMP、JPEG、GIF三种格式,并能运行于Windows和Linux。为方便扩展新的文件格式、操作系统并减少所需子类数量,采用桥接(Bridge)模式,类图如图6-1。

阅读Java代码,填写空(1)~(5)。

import java.util.*;

class Matrix{ // 各种格式的文件最终都被转化为像素矩阵

// 此处代码省略

};

abstract class Implementor{

public (1); // 显示像素矩阵 m

};

class WinImp extends Implementor{

public void doPaint(Matrix m){ // 调用 Windows 系统的绘制函数绘制像素矩阵

}

};

class LinuxImp extends Implementor{

public void doPaint(Matrix m){ // 调用 Linux 系统的绘制函数绘制像素矩阵

}

};

abstract class Image {

public void setImp(Implementor imp) { this.imp = imp; }

public abstract void parseFile(String fileName);

protected Implementor imp;

};

class BMPImage extends Image{

// 此处代码省略

};

class GIFImage extends Image{

public void parseFile(String fileName) {

// 此处解析 BMP 文件并获得一个像素矩阵对象 m

(2); // 显示像素矩阵 m

}

};

class JPEGImage extends Image{

//此处代码省略

};

class Main{

public static void main(String[]args) {

// 在 Linux 操作系统上查看 demo.gif 图像文件

Image image= (3);

Implementor imageImp= (4);

(5);

image.parseFile("demo.gif");

}

}
答案与解析

平台参考答案(原文保留)

1.abstract void doPaint(Matrix m)
2.imp.doPaint(m)
3.new GIFImage()
4.new LinuxImp()
5.image.setImp(imageImp)

解析与纠错

(1)在已有public后补abstract void doPaint(Matrix m),(2)为imp.doPaint(m);(3)/(4)分别new GIFImage()、new LinuxImp(),(5)为image.setImp(imageImp)。这与C++题同属桥接意图,但Java抽象方法和引用调用的原空不同,保留为独立题。

GIFImage的注释却写“解析BMP文件”,与类名及demo.gif不一致;所示代码没有声明矩阵m,也没有真实解析过程。BMPImage、JPEGImage不是abstract,却明示省略了parseFile实现,JPEGImage尾还用全角分号;照抄不能直接编译。原页已核实BMP注释、未声明m、两个非abstract占位类及全角分号均如此;main以parseFile调用和两个闭括号结束后即知识点。来源完整,显式省略不作为提取缺失。

补充测试明确将未用的占位子类标为abstract,整理全角分号,并在GIFImage中提供测试矩阵;这些属于测试补全。验证的是图像对象向当前绘制实现传递矩阵,支持换绘制实现及新增格式,不包括文件解码算法或操作系统图形接口。

2017年上半年软件设计师案例真题:案例题

本节保留 3 条来源,答案与解析默认收起。

2017-05-case Q003

电动玩具订单的类与状态设计

某玩具公司建设电动玩具在线销售系统,向注册会员提供端对端的定制与销售服务。创建新订单(New Order)的详细设计用例、候选设计类分类和部分类图分别见表3-1、表3-2、图3-1。用例的前提、典型事件流、候选事件流3a/7a及C1~C12标记均保留在表中。

表3-1 创建新订单设计用例

表3-2 候选设计类分类

图3-1 部分类图

订单处理时会员可点击“取消订单”。支付失败则挂起,可稍后重新支付;挂起超过30分钟仍未支付,系统自动取消。支付成功后,按订单类型处理:常规订单进入备货,将订单信息发送货运部,打包后交付快递;定制订单进入定制,完成后交付快递。会员点击“收货”后进入收货状态,结束处理。图3-2给出相应状态图。

【问题1】(6分)将表3-1的候选设计类C1~C12按类别填入表3-2的(a)、(b)、(c)。

【问题2】(4分)按创建新订单用例,填写图3-1中X1~X4的类名。

【问题3】(5分)按订单处理过程,填写图3-2中S1~S5的状态名。

答案与解析

平台参考答案(原文保留)

【问题1】

(a):C2、C4、C7、C10、C11

(b):C3、C5、C8

(c):C1、C6、C9、C12

【问题2】

X1:收货地址

X2:支付方式

X3:邮箱地址

X4:电动玩具定制属性

【问题3】

S1:订单挂起

S2:订单备货

S3:订单定制

S4:订单发货

S5:订单收货

解析与纠错

表中的分类标准是职责:显示列表、确认支付信息和完整订单的是边界/接口类,故(a)为C2、C4、C7、C10、C11;总价计算、调用支付、发送订单信息是控制行为,故(b)为C3、C5、C8;会员、订单、邮箱、支付方式是持久信息,故©为C1、C6、C9、C12。C2等在此指展示这些信息的界面职责,不是说“价格”等业务数据在所有建模中都只能作为接口类。

会员资料及订单都使用收货地址和支付方式。图中Profile只关联一个X1,却可关联多个X2;结合候选流7a允许新增并设为默认支付方式,得到X1收货地址、X2支付方式。资料另关联X3邮箱地址,玩具关联X4定制属性(尺寸、颜色等)。

沿事件判状态:支付失败到S1挂起,重新支付返回订单处理,超时到终止;常规订单到S2备货、定制订单到S3定制,两支交付快递后均到S4发货;确认收货到S5收货,再结束。图中“订单类型”两支结合文字的支付成功前提阅读,不能把支付失败也送去备货。

2017-05-case Q005

套餐制作的C++填空

快餐厅制作儿童套餐,通常包括主餐(各类比萨)、饮料、玩具。餐品种类可不同,制作过程相同,由前台服务员Waiter调度厨师。采用生成器(Builder)模式实现制作过程,类图见图5-1。

阅读C++程序,填写空(1)~(5)。

#include < iostream >  
#include < string >  
using namespace std;  

class Pizza {  
private: string parts;  
public:  
void setParts(string parts) { this- > parts=parts; }  
string getParts() { return parts; }  
};  
class PizzaBuilder {  
protected:Pizza* pizza;  
public:  
Pizza* getPizza() { return pizza; }  
void createNewPizza() { pizza = new Pizza(); }  
(1);  
}  
class HawaiianPizzaBuilder:public PizzaBuilder {  
public:  
void buildParts() { pizza- > setParts("cross +mild + ham&pineapple"); }  
};  

class SpicyPizzaBuider: public PizzaBuilder {  
public:  
void buildParts() { pizza- > setParts("pan baked +hot + ham&pineapple"); }  

}  

Class Waiter{  
Private:  
PizzaBuilder* pizzaBuilder;  
public:  
void setPizzaBuilder(PizzaBuilder* pizzaBuilder) { /*设置构建器*/  
(2)  
}  
Pizza* getPizza() { return pizzaBuilder- > getPizza(); }  
void construct() { /*构建*/  
pizzaBuilder- > createNewPizza();  
(3)  
}  
};  

int main(){  
Waiter*waiter=new Waiter();  
PizzaBuilder*hawaiian pizzabuilder=new HawaiianPizzaBuilder()  

(4);  
(5);  
cout < < "pizza: " < < waiter- > getPizza()- > getParts() < < endl;  
}

题目给出的输出为:

pizza: cross + mild + ham&pineapple
答案与解析

平台参考答案(原文保留)

(1)virtual void buildParts()=0
(2)this- > pizzaBuilder=pizzaBuilder
(3)pizzaBuilder- > buildParts()
(4)waiter- > setPizzaBuilder(hawaiian_pizzabuilder)
(5)waiter- > construct()

解析与纠错

Pizza为产品,PizzaBuilder规定创建产品和构建部件,具体生成器决定部件内容;Waiter负责依次创建、构建,并取得成品。(1)用纯虚函数virtual void buildParts()=0;(2)保存传入的生成器指针;(3)在创建Pizza后调用其buildParts;(4)把夏威夷生成器交给waiter;(5)调用construct。换另一生成器可沿用同一制作流程。

原代码的指针箭头被拆开,Class/Private大小写不合C++语法,PizzaBuilder和SpicyPizzaBuider类末缺分号;(2)、(3)所在行及平台对应答案均未给分号,main的变量名含空格,new语句也缺分号。整理版需明确统一为hawaiian_pizzabuilder并补齐语法,不能说填五空后即可直接编译。原图夏威夷类方法写builderParts,而代码及基类为buildParts,整理版按基类统一。

即便只修语法,代码字符串仍是cross +mild + ham&pineapple,与题给输出cross + mild + ham&pineapple在加号后空格上不一致;原题两处分别保留,不暗改产品内容。程序只给出Pizza部分,套餐说明中的饮料、玩具没有实现,不推断它们已被完整构建。

行为测试使用整理代码验证先创建后构建、切换生成器、再次构建得到新产品,并区分代码字面输出与题给输出。原题未给对象生命周期管理;测试自行释放已分配的具体对象,不将测试清理代码冒充原题,也不通过缺少虚析构的基类指针删除派生对象。

原站可见页面截图已核实,类末和第(2)、(3)空所在行缺分号、Class/Private大写、main变量名含空格及new行缺分号均为原题写法;代码字符串与题给输出的空格差异也确实存在。最后cout及闭括号后直接是输出说明,没有其他代码,来源完整。

2017-05-case Q006

套餐制作的Java填空

快餐厅制作儿童套餐,通常包括主餐(各类比萨)、饮料、玩具。餐品种类可不同,制作过程相同,由前台服务员Waiter调度厨师。采用生成器(Builder)模式实现制作过程,类图见图6-1。

阅读Java程序,填写空(1)~(5)。

class Pizza {

private String parts;

public void setParts(String parts) { this.parts = parts; }

public String toString() { return this.parts; }

}

abstract class PizzaBuilder {

protected Pizza pizza;

public Pizza getPizza() { return pizza; }

public void createNewPizza() { pizza = new Pizza(); }

public (1);

}

class HawaiianPizzaBuilder extends PizzaBuilder {

public void buildParts() { pizza.setParts("cross + mild + ham&pineapp1e”};

}

class SpicyPizzaBuilder extends PizzaBuilder {

public void buildParts() { pizza.setParts("pan baked + hot + pepperoni&salami"); }

}

class Waiter {

private PizzaBuilder pizzaBuilder;

public void setPizzaBuilder(PizzaBuilder pizzaBuilder) { /*设置构建器*/

( 2 );

}

public Pizza getPizza(){ return pizzaBuilder.getPizza(); }

public void construct() { /*构建*/

pizzaBuilder.createNewPizza();

( 3 );

}

}

Class FastFoodOrdering {

public static viod mainSting[]args) {

Waiter waiter = new Waiter();

PizzaBuilder hawaiian_pizzabuilder = new HawaiianPizzaBuilder();

( 4 );

( 5 );

System.out.println("pizza: " + waiter.getPizza());

}

}

题目给出的输出为:

Pizza:cross + mild + ham&pineapple
答案与解析

平台参考答案(原文保留)

(1)abstract void buildParts();

(2)this.pizzaBuilder=pizzaBuilder

(3)pizzaBuilder.buildParts()

(4)waiter.setPizzaBuilder(hawaiian_pizzabuilder)

(5)waiter.construct()

解析与纠错

Java的PizzaBuilder是抽象类,(1)补抽象buildParts声明;(2)保存生成器引用,(3)在createNewPizza后调用buildParts,(4)设置夏威夷生成器,(5)构建。Pizza重写toString,因此字符串拼接会显示parts;这与C++显式调用getParts的原空不同,保留独立题。

原字段后全角分号、Class、viod和mainSting[]args)不符合Java语法;夏威夷部件语句含弯引号,方法调用与括号也残损。整理版需明确修成标准main(String[] args)及完整的setParts调用,原题代码仍原样保留。平台(1)答案自带分号,而题面空后另有分号;Java类体允许额外空声明,但学习代码只需一个终止分号。

字符串末尾原写pineapp1e(数字1),题给输出却为pineapple(字母l);代码打印前缀为pizza:,题给输出是Pizza:,大小写和空格也不一致。只修语法的测试保留这些字面内容,不能声称会输出题后那一行。类图夏威夷方法builderParts与代码buildParts也不一致,测试按基类接口统一。两种语言的Spicy部件原文也不同,不能拿另一题的字符串替换本题。

测试验证生成流程、切换两种生成器、产品重新创建和toString输出。只覆盖题中Pizza构建,不臆补饮料、玩具或未说明的套餐逻辑。

原站可见页面已核实上述全角分号、数字1、弯引号、缺右括号、main签名、两处分号及输出标签大小写均为原题写法。末尾两个闭括号后直接给出程序输出说明,没有其他代码;来源完整,语法整理不作为原题原文。

2016年下半年软件设计师案例真题:案例题

本节保留 3 条来源,答案与解析默认收起。

2016-11-case Q003

自动售货机的状态与类设计

出售罐装饮料的自动售货机(Vending Machine)按以下流程工作。

  1. 顾客选择饮料及数量。
  2. 顾客从投币口投入硬币,机器只接收硬币。硬币器收集硬币并计算其价值;金额足够且所选饮料库存足够时,推出饮料、计算找零,顾客取走饮料和找零。金额不足或库存不足时,提示继续投币或重选饮料及数量。
  3. 一次购买结束后移走硬币器中的硬币,即清空硬币器,等待下次交易。另设退币按钮退回顾客投入的硬币,已成功购买饮料的钱不退。

图3-1为用例图。

“购买饮料”的参与者为顾客。主要事件流依次为:①选饮料及数量并投币;②检查投入硬币是否足够;③检查饮料储存仓中所选饮料是否足够;④推出饮料;⑤返回找零。备选流2a在硬币不足时提示并返回步骤1,3a在库存不足时提示并返回步骤1。

据此得到“空闲”“准备服务”“可购买”“饮料出售”四种状态;图3-2给出状态图,图3-3给出类图。

【问题1】(6分)用说明中的术语填写图3-2中S1~S4的状态名。

【问题2】(4分)用说明中的术语填写图3-2中E1~E4的事件名。

【问题3】(5分)用说明中的术语填写图3-3中C1~C5的类名。

答案与解析

平台参考答案(原文保留)

【问题1】
S1:空闲,S2:准备服务,S3:饮料出售,S4:可购买。
【问题2】
E1:饮料数量不足,E2:选择饮料【硬币数量足够】。

E3:饮料数量足够/推出饮料,E4:取走饮料/返回找零并清空硬币器。

【问题3】

C1:自动售货机

C2:硬币器,C3:饮料储存仓,C4:硬币,C5:饮料。/C2:饮料储存仓,C3:硬币器,C4 :饮料;C5:硬币。

解析与纠错

S1能在清空硬币器后等待交易,为空闲;投币并计算价值进入S2准备服务;金额足够后进入S4可购买;推出饮料进入S3饮料出售。图中的S3、S4顺序与题干列举顺序不同,应沿箭头判断。

E1是库存不足,S4退回S2提示重新选择;E2按平台写选择饮料并满足硬币足够条件;E3为饮料足够时推出饮料;E4为取走饮料后返回找零、清空硬币器,回到空闲。标准状态转移标签可区分“事件[条件]/动作”,不能把条件本身都当成外部事件。平台“硬币数量足够”应结合题干解释为硬币总价值足以支付所选数量的饮料,不是仅数硬币枚数;不同面值不能只比数量。

C1是自动售货机,拥有硬币器和饮料储存仓;它们分别容纳0..*个硬币与饮料。因此可取C2硬币器、C4硬币,C3储存仓、C5饮料;图中两个分支结构相同,也可把C2/C4与C3/C5成对交换。不能只换父类名、不同时换其所容纳的对象。

原用例还包含退还硬币,但这张购买状态图未单独画全退币按钮的事件,不据此增补原题空位或宣称图已经覆盖全部退款规则;已完成购买的金额仍按说明不退。

2016-11-case Q005

发票打印的C++填空

发票Invoice由抬头Head、正文和脚注Foot构成。使用装饰(Decorator)模式实现打印功能,类图见图5-1。

阅读C++代码,填写空(1)~(5)。代码末注释保留题目给出的输出。

#include <iostream>

using namespace std;

class Invoice {

public:

______(1) ______ {

cout << "This is the content of the invoice!" << endl;

}

};

class Decorator: public Invoice{

Invoice *ticket;

public:

Decorator(Invoice *t) { ticket = t; }

void printInvoice() {

if(ticket!= NULL)

______ (2) ______;

}

};

class HeadDecorator: public Decorator{

public:

HeadDecorator(Invoice *t): Decorator(t) {

}

void printInvoice() {

cout << "This is the header of the invoice!" << endl;

______ (3) ______;

}

};

class FootDecorator: public Decorator{

public:

FootDecorator(Invoice *t): Decorator(t) {

}

void printInvoice() {

______ (4) ______;

cout << "This is the footnote of the invoice!" << endl;

}

};

int main(void) {

Invoice t;

FootDecorator f(&t);

HeadDecorator h(&f);

h.printInvoice();

cout << "---" << endl;

FootDecorator a(NULL);

HeadDecorator b(______(5)______);

b.printInvoice();

return 0;

}

/*

程序的输出结果为:

This is the header of the invoice!

This is the content of the invoice!

This is the footnote of the invoice!

---

This is the header of the invoice!

This is the footnote of the invoice!

*/
答案与解析

平台参考答案(原文保留)

(1) virtual void printInvoice()

(2) ticket- > printInvoice()

(3) Decorator::printInvoice()

(4) Decorator::printInvoice()

(5) &a

解析与纠错

Invoice定义可多态调用的printInvoice,所以(1)必须带virtual;Decorator保存被包装对象ticket,不为空时由(2)委托打印。HeadDecorator先输出抬头,再通过(3)调用Decorator的委托逻辑;FootDecorator先通过(4)委托,再输出脚注。两处显式基类调用避免把自己再次调用而无限递归。

第一次装配h→f→t,打印抬头、正文、脚注。第二次a的内部指针为NULL,第(5)空取&a,将b包装在a外,得到抬头、脚注而没有正文。a是栈对象,传入它的地址,不是把对象本身传给指针参数;装饰器对空组件的检查使第二次调用有效。

平台第(2)项箭头分开写作“- >”,保留原答案;真正C++运算符应为->。将此排版整理后,给出的完整main可编译,实际六行内容与分隔线输出符合题目。对象都在栈上,题面没有通过基类指针delete派生对象,因此本题不需要假装存在未给出的所有权或析构实现。

额外测试验证基类指针虚派发、空组件、重复包装和基础对象输出不变。图只展示继承层次;实际装饰转发还依赖代码中的ticket成员,不能把装饰理解为单纯覆盖一个输出函数。

2016-11-case Q006

发票打印的Java填空

发票Invoice由抬头Head、正文和脚注Foot构成。使用装饰(Decorator)模式实现打印功能,类图见图6-1。

阅读Java代码,填写带下划线的空(1)、(2)、(3)、(4)、(5)。

class invoice{

public void printInvoice(){

System.out.println ( "This is the content of the invoice!");

}

}

class Decorator extends Invoice {

protected Invoice ticket;

public Decorator(Invoice t){

ticket = t;

}

public void printInvoice(){

if(ticket!= null)

(1

)

;

}

}

class HeadDecorator extends Decorator{

public HeadDecorator(Invoice t){

super(t);

}

public void printInvoice (){

Systent.out.println( "This is the header of the invoice! ");

(2

)

;

}

}

class FootDecorator extends Decorator {

public FootDecorator(Invoice t){

super(t);

}

public void printInvoice(){

( 3

)

;

Systent.out.println( "This is the footnote of the invoice! ");

}

}

Class test {

public static void main()(String[] args){

Invoice t =new Invioce();

Invoice ticket;

ticket=

(4

)

;

ticket.printInvoice();

Systent.out.println(“------------------“);

ticket=

(5

)

;

ticket.printInvoice();

}

}

题目给出的输出为:

This is the header of the invoice!

This is the content of the invoice!

This is the footnote of the invoice!

----------------------------

This is the header of the invoice!

This is the footnote of the invoice!
答案与解析

平台参考答案(原文保留)

(1) ticket.printInvoice()

(2) super.printInvoice()

(3) super.printInvoice()

(4) new HeadDecorator(new FootDecorator(t))

(5) new HeadDecorator(new FootDecorator(null))

解析与纠错

(1)对被包装的ticket调用printInvoice;(2)、(3)调用super.printInvoice,复用Decorator的空检查与委托。第(4)空将已有t先包脚注、再包抬头;第(5)空以null作最内层组件,仍保留脚注及抬头,所以不打印正文。Java动态派发不需要C++的virtual关键字,两个语言的原空与装配目标分别保留。

原代码class invoice与所用Invoice大小写不同,new Invioce拼错,Systent、Class以及main()(String[] args)也不是合法写法;分隔线使用弯引号。整理版仅修这些语法,保留原题代码在上方,不把补正当作原文。

代码的分隔线有18个“-”,题后给定输出有28个;抬头、脚注代码字符串在感叹号后还有一个空格,题给输出没有。因此仅修编译错误仍不能与题后输出逐字符相同,正文保留两者差异;测试分别核对调用顺序及代码实际字面输出,不暗改字符串。

平台解析把super调用的理由归于“借助超类构造函数”,这个表述不精确:构造函数设置包装对象,super.printInvoice则显式调用超类的普通方法。直接再次调用自身printInvoice会递归;改为调用Invoice的基本正文也会绕过包装链及null分支。

原站可见页面截图已核实上述大小写、拼写、main签名、弯引号、字符串尾空格及分隔线长度差异。五个待填位置均带下划线;末尾函数与类的两个闭括号后直接是程序输出说明,没有额外类或代码,来源完整。

2016年上半年软件设计师案例真题:案例题

本节保留 3 条来源,答案与解析默认收起。

2016-05-case Q003

虚拟世界与机器人的用例及类设计

某软件公司拟实现虚拟世界仿真系统。用户设置并创建不同环境以模拟现实世界,通过1~2个机器人探索;机器人用b1、b2两个变量保存读出的字符。

系统包含以下功能。

  1. RunRobots:用户用Editor编写环境文件,经LoadFile导入,完成SetupWorld;另在文件中定义机器人的行为,完成SetupProgram。RunProgram有两种模式:Run按预编排的Instruction序列连续动作,若干条Instruction构成InstructionSet;Step是自动控制的特殊形式,每次只执行指定指令的一个动作。
  2. ManipulateRobots:先SelectRobot选定1个机器人,再手动控制。Move使它向正前方移动一个交叉点;Left使它原地逆时针转90度;Read读取当前位置字符赋给b1,若没有字符则b1不变;Write把b1中的字符写到当前位置,已有字符则覆盖。若b1尚无值,即说明中所说Write前未执行过Read,则ShowErrors提示错误。

Step每次只能执行指令中的下个动作;手动方式有上述4种动作可选。采用面向对象方法得到图3-1用例图和图3-2初始类图;Interpreter、Parser用于解析环境文件及机器人行为文件中的指令集。

【问题1】(6分)按说明填写图3-1中U1~U6的用例名。

【问题2】(4分)说明U1~U6分别与哪个(哪些)用例有关系,以及关系类型。

【问题3】(5分)按说明填写图3-2中C1~C5的类名。

答案与解析

平台参考答案(原文保留)

【问题1】

U1/U2:Run、Step U3:Write U4/U5/U6:Move、Left、Read 【问题2】 U1和U2和RunProgram有泛化关系。 U3,U4,U5,U6和 Manipulate Robots 有泛化关系。

【问题3】

C1:World/虚拟世界

C2:Robot/Robots

C3:Instruction

C4:InstructionSet

C5:Error/Errors

解析与纠错

U1、U2对应Run、Step,两者位置可交换;U3与ShowErrors相连,依据无字符值时Write报错确定为Write;U4~U6可依次填Move、Left、Read,三者位置可交换。

按平台参考答案,Run、Step分别泛化到RunProgram,四种手动动作分别泛化到ManipulateRobots。泛化箭头的空心三角指向一般用例,不能画成动作调用的普通实线箭头。题目将Step称为自动控制的特殊形式,但平台的预期空位是Run和Step同列为RunProgram的特化,不额外改变原图。

问题2问到“哪个(哪些)用例”,而U3与ShowErrors的关系已画在原图中,平台文字答案只列了待补泛化关系。现图的普通箭头缺少标准UML关系标注,不能直接说它已明确标成include或extend。若另作标准用例建模,错误提示仅在b1无值时出现,可由ShowErrors以extend指向Write,并注明触发条件;无条件include会误说每次写都报错。

C1包含1~2个C2,因此是World和Robot;C4聚合1..n个C3,因此是InstructionSet和Instruction;C1依赖C5,对应Error。Interpreter、Parser与World/InstructionSet相连,不应把World本身答成解释器或文件解析器。

原说明把“b1没有值”等同于“从未执行Read”并不严密:机器人在无字符位置执行Read时b1不变,仍可能无值。实际判断应检查b1是否已有有效值;保留原条件但不沿用该等价推论。b2虽在背景出现,题目未给其读写规则,不擅自补用法。

2016-05-case Q005

Dutch地址接口的C++填空

现有Address类已实现地址信息显示,现需提供Dutch语言接口,并考虑以后增加其他语言接口。采用适配器(Adapter)模式,类图如图5-1。

阅读C++代码,填写空(1)~(5)。

#include < iostream >

using namespace std;

class Address{

public:

void stree() { /* 实现代码省略 */ }

void zip() { /* 实现代码省略 */ }

void city() { /* 实现代码省略 */ }

∥其他成员省略

};

class DutchAddress {

public:

virtual void straat()=0;

virtual void postcode()=0;

virtual void plaats()=0;

//其他成员省略

};

class DutchAddressAdapter: public DutchAddress {

private:

(1);

public:

DutchAddressAdapter(Address *addr) {

address = addr;

}

void straat() {

(2);

}

void postcode(){

(3);

}

void plaat(){

(4);

}

//其他成员省略

};

void testDutch(DutchAddress *addr){

addr- > straat();

addr- > postcode();

addr- > plaats();

}

int main(){

Address*addr = new Address();

(5);

cout < < "\n The DutchAddress\n" < < endl;

testDutch(addrAdapter);

return 0;

}
答案与解析

平台参考答案(原文保留)

(1)Address *address;

(2)address- > street();

(3)address- > zip();

(4)address- > city();

(5)DutchAddress *addrAdapter=new DutchAddressAdaptor(addr);

解析与纠错

DutchAddress是客户端要求的接口,Address是已有实现;DutchAddressAdapter继承前者并保存指向后者的指针。(1)为Address *address;三个目标方法分别委托street、zip、city;(5)建立适配器并通过DutchAddress指针交给testDutch。适配器转换接口,不凭空实现题目省略的地址显示内容。

原文存在三组相互冲突的拼写:Address代码写stree而图和答案用street;接口声明plaats而适配器写plaat;实际类名为DutchAddressAdapter,平台第(5)项却写DutchAddressAdaptor。直接填平台答案会分别造成找不到成员、派生类仍为抽象类、找不到类型,不能说原代码填空后即可编译。整理版分别统一为street、plaats、DutchAddressAdapter;平台原答案仍按原拼写保留。

∥并非C++行注释,头文件内空格、分开的箭头与输出运算符也需整理。五个原空后已有分号,答案行的末尾分号不必重复加入。Address与其他成员均明确省略,测试不能把省略理解为已提供真实地址翻译算法。

最小整理版把明确省略的方法体留空,可编译运行原main,但只输出题给标题;行为测试另外明确在省略处记录调用,验证虚接口派发及straat→street、postcode→zip、plaats→city的对应。Address这些方法本身非virtual,不能用假定的子类动态覆盖来证明其委托。

原站可见页面已核实上述方法名、类名及参考答案的拼写差异;首处省略说明前是双划字形,区别于后面的正常//。main结尾后无额外代码,原空后已有分号。这些原题写法均保留,语法整理和更正仅在解析中说明。

2016-05-case Q006

Dutch地址接口的Java填空

现有Address类已实现地址信息显示,现需提供Dutch语言接口,并考虑以后增加其他语言接口。采用适配器(Adapter)模式,类图如图6-1。

阅读Java代码,填写空(1)~(5)。

import java.util.*;

Class Address{

public void street() { //实现代码省略 }

public void zip() { //实现代码省略 }

public void city() { //实现代码省略 }

//其他成员省略

};

class DutchAddress{

public void straat() { //实现代码省略 }

public void postcode() { //实现代码省略 }

public void plaats() { //实现代码省略 }

//其他成员省略

};

class DutchAddressAdapter extends DutchAddress {

private (1);

public DutchAddressAdapter (Address addr){

address= addr;

}

public void straat() {

(2);

}

public void postcode() {

(3);

}

public void plaats(){

(4);

}

//其他成员省略

};

class Test {

public static void main(String[] args) {

Address addr= new Address();

(5);

System.out.println("\n The DutchAddress\n");

testDutch(addrAdapter);

}

Static void testDutch(DutchAddress addr){

addr.straat();

addr.postcode();

addr.plaats();

}

}
答案与解析

平台参考答案(原文保留)

(1)Address address;

(2)address.street();

(3)address.zip();

(4)address.city();

(5)DutchAddress addrAdapter=new DutchAddressAdapter(addr);

解析与纠错

Java中适配器用成员Address address保存被适配对象,构造函数接收并记录它;straat、postcode、plaats分别调用address.street()、address.zip()、address.city()。最后创建DutchAddressAdapter赋给DutchAddress引用,testDutch通过多态调用适配器三个方法。成员类型仍是Address,不能改成目标接口DutchAddress而导致委托方向错误。

原文本的Class、Static首字母大写不合法;Address和DutchAddress的六个占位方法把闭合右括号写在//行注释后,按现有换行直接编译时右括号会被注释掉。明确整理版将关键字改小写,并把“实现代码省略”改为块注释,让右括号生效;没有臆造被省略的地址显示实现。五处原空和平台答案均带末尾分号,整理填空只保留一份分号,平台原答案不改。

使用空占位体可验证整理后的完整程序编译,运行只显示标题。独立行为测试以记录调用的Address子类替代省略行为,验证目标接口的动态派发、三个方法对应、多个适配器各自保存正确对象及重复调用;不据此声称地址本地化功能已经实现。

原站可见页面已核实Class、Static的大小写及六个行注释后同一行的右括号;main之后是testDutch,最后两个右括号后无额外成员。五个题面空后和五项参考答案末尾均有分号,原题和原答案各自保留。

2015年上半年软件设计师案例真题:案例题

本节收录 3 道案例,答案与解析默认收起。

2015-05-case Q003

拍卖平台的类模型

某拍卖网站组织物品拍卖,并支持在线与线下交易。参与者分个人和团体,不同团体还可组成新的团体参加拍卖;每个参与者均记录名称。

一次拍卖中,参与者担任买方或卖方。每次只拍卖一位卖方的一件物品,多名买方可出价,卖方接受一个出价后结束拍卖。结算有两种方式:线下在约定地点当面付款交货;在线由买方通过网上支付平台付款,卖方通过快递邮寄物品。

一次拍卖的基本事件流如下:

  1. 卖方在网站发起拍卖并设置起拍价。
  2. 确定拍卖标的及保留价;若拍卖时间结束时所有出价均低于保留价,拍卖失败。
  3. 发布拍卖品介绍。
  4. 买方参与并给出竞拍价。
  5. 卖方接受一个竞拍价作为成交价,结束拍卖。
  6. 系统记录成交价,进入结算。
  7. 双方协商成交方式并完成成交。

采用面向对象方法得到表3-1的类列表、图3-1的类图,以及表3-2的关键属性和方法列表。

【问题1】(7分)确定图3-1中(1)~(7)的类名,用表3-1的类序号作答。

【问题2】(5分)确定表3-2中每个属性或方法属于哪个类,使用表3-1、表3-2中的序号作答。

【问题3】(3分)指出图3-1采用的设计模式,并用100字以内说明采用原因。

答案与解析

平台参考答案(原文保留)

【问题1】

注意:C8和C10可互换,互换后在问题2中也必须交换对应位置。

【问题2】

【问题3】

组合模式,在本题中由于拍卖者分为个人参与者和团体参与者两种,而团体也可以组成新的团体参与拍卖活动。这样的整体部分关系,适合于使用组合模式表达。

解析与纠错

从两组泛化关系入手:参与者是共同抽象,个人和团体是其特例,因此(1)为C5、(2)为C9、(3)为C7;成交方式是共同抽象,线下与在线是其特例,因此(4)为C6、(5)为C8、(6)为C10;与一次拍卖对应的物品是(7)C2。

按参考答案整理属性与职责:

属性或方法 所属类 判断依据
M1 C5 所有参与者的名称
M2 C2 拍卖品介绍
M3 C3 拍卖活动的起拍价
M4 C4 结算采用的成交价
M5 C11 原表按Bid分配,术语问题见下文
M6 C8 线下交付地点
M7、M8 C10 在线付款账号、邮寄地址
M9 C12 买方出价
M10 C1 卖方发起拍卖

问题3可答:采用组合模式。以共同参与者接口表示个人与团体,团体可包含其他参与者,递归表达整体与部分,使调用者能以一致方式处理个人和团体。

补充说明

订正与图示限制:C11的类名Bid通常表示一次出价,但原类表说明写成“拍卖标的”,M5又把Bid Price描述为保留价。按照参考答案保留M5→C11;实际建模应把买方出价与卖方设定的保留价区分,不能把二者视为同一数值。

原图在(1)参与者一端画了聚合菱形,和“(2)团体包含参与者”的整体方向不一致;按组合模式解释时,整体应是团体。参考答案的类填空仍保留,不以该菱形位置证明整体方向。图上0..1归属限制也比文字中的一般团体组合更强,不宜据此断言任何业务中成员都只能属于一个团体。

(5)、(6)位置可以互换,但C8始终代表OfflinePay,C10始终代表OnlinePay;交换图中位置不会改变M6→C8、M7/M8→C10这些固定类编号对应关系。原答案的“问题2也必须交换对应位置”仅能理解为同步图示位置,不能改写类本身含义。

下表为来源解析中的属性对应表,与参考答案表一致:

2015-05-case Q005

馆藏页数统计(C++)

图书管理系统保存图书和论文两类文献,需要统计全部馆藏文献的总页码。例如,一本540页的图书加两篇各25页的论文,共590页。按Visitor(访问者)模式设计,类图如下。

图5-1 Visitor模式类图。

根据说明与下列C++代码填写(1)~(5)。

class LibraryVisitor;

class LibraryItemInterface{

public:

(1);

};

class Article: public LibraryItemInterface {

private:

string m_title; //论文名

string m_author; //论文作者

int m_start_page;

int m_end_page;

public:

Article(string p_author, string p_title, int p_start_page,int p_end_page );

int getNumberOfPages();

void accept(Library Visitor* visitor);

};

class Book: public LibraryItemInterface {

private:

string m_title; //书名

string m_author; //作者

int m_pages; //页数

public:

Book(string p_author, string p_title, int p_pages);

int getNumberOfPages();

void accept(LibraryVisitor* visitor);

};

class LibraryVisitor {

public:

(2);

(3);

virtual void printSum() = 0;

};

class LibrarySumPrintVisitor: public LibraryVisitor { //打印总页数

private:

int sum;

public:

LibrarySumPrintVisitor();

void visit(Book* p_book);

void visit(Article* p_article);

void printSum();

};

// visitor.cpp

int Article::getNumberOfPages(){

retum m_end_page - m_start_page;

}

void Article::accept(LibraryVisitor* visitor) { (4);}

Book::Book(string p_author, string p_title, int p_pages ) {

m_title = p_title;

m_author = p_author;

m_pages = p_pages;

}

int Book::getNumberOfPages(){ return m_pages; }

void Book::accept(LibraryVisitor* visitor){ (5); }

//其余代码省略
答案与解析

平台参考答案(原文保留)

(1)virtual void accept(LibraryVisitor* visitor)=0

(2)virtual void visit(Book* p_book)=0

(3)virtual void visit(Article* p_article)=0

(4)visitor- > visit(this)

(5)visitor- > visit(this)

解析与纠错

LibraryItemInterface是被访问元素接口,第(1)空声明纯虚accept;LibraryVisitor分别声明接受Book*和Article*的纯虚visit,对应第(2)、(3)空。两个具体元素的accept都把自身交给访问者,因此第(4)、(5)空均为visitor->visit(this)。

调用先经元素的虚accept确定具体元素,再在其内部按this的静态类型选择visit重载,并通过访问者虚函数执行具体访问操作。仅有同名重载,不足以代替这种两步分派。添加新的统计操作通常只需增加访问者;添加新的元素类型通常要同时扩展访问者接口。

补充说明

原代码问题与解释边界:所给代码中的“Library Visitor”被空格拆开,“retum”应为return;原答案里的“visitor- >”在C++中应写成visitor->。题面明确省略其余代码,因此缺少头文件、部分构造函数和访问者方法实现,不能声称仅填五空便得到完整可执行程序。

Article页数写为end-start,只有结束位置不包含在区间内时才合适;若start、end都是实际首尾页码,应为end-start+1。例如第10~34页首尾都计入时是25页,而[10,35)也是25页。题面只给“各25页”而没有指定页码区间约定,不能据此无条件改成其中一种。

测试分别采用上述两种明确区间约定,540页图书加两篇25页论文都得到590;补入的构造函数和访问者实现仅作演示。下面是原解析的通用结构图:

2015-05-case Q006

馆藏页数统计(Java)

图书管理系统保存图书和论文两类文献,需要统计全部馆藏文献的总页码。例如,一本540页的图书加两篇各25页的论文,共590页。按Visitor(访问者)模式设计,类图如下。

图6-1 Visitor模式类图。

根据说明与下列Java代码填写(1)~(5)。

import java.util.*;

interface LibraryVisitor {

(1);

(2);

void printSum();

}

class LibrarySumPrintVisitor implements LibraryVisitor { //打印总页数

private int sum = 0;

public void visit(Book p_book) {

sum = sum + p_book.getNumberOfPages();

}

public void visit(Article p_article) {

sum = sum + p_article.getNumberOfPages();

}

public void printSum(){

System.out.println("SUM = " + sum);

}

}

interface LibraryItemInterface {

(3);

}

class Article implements LibraryItemInterface{

private String m_title; //论文名

private String m_author; //论文作者

private int m_start_page;

private int m_end_page;

public Article(String p_author, String p_title,int p_start_page,int p_end_page){

m_title=p_title;

m_author= p_author;

m_end_page=p_end_page;

}

public int getNumberOfPages(){

return m_end_page - m_start_page;

}

public void accept(LibraryVisitor visitor){

(4);

}

}

class Book implements LibraryItemInterface{

private String m_title; //书名

private String m_author; //书作者

private int m_pages; //页教

public Book(String p_author, String p_title,int p_ pages){

m_title= p_title;

m_author= p_author;

m_pages= p_pages;

}

public int getNumberOfPages(){

return m_pages;

}

public void accept(LibraryVisitor visitor){

(5);

}

}
答案与解析

平台参考答案(原文保留)

(1)void visit(Book p_book)

(2)void visit(Article p_article)

(3)void accept(LibraryVisitor visitor)

(4)visitor.visit(this)

(5)visitor.visit(this)

解析与纠错

LibraryVisitor声明void visit(Book p_book)和void visit(Article p_article),分别填第(1)、(2)空。LibraryItemInterface声明void accept(LibraryVisitor visitor),填第(3)空。Article、Book的accept调用visitor.visit(this),填第(4)、(5)空。

即使集合元素的引用类型为LibraryItemInterface,运行时仍会进入具体元素的accept;其中this分别是Article或Book,选择对应visit重载。sum属于一次访问者实例,遍历集合时累计;重新用同一实例遍历会继续累加,开始另一轮独立统计应新建访问者或显式重置。

补充说明

原代码问题与行为纠错:Book构造参数中出现“p_ pages”,直接编译会失败。Article构造函数没有给m_start_page赋值;Java实例整数字段会默认为0,因而实际返回end-0,并不等于用传入起始页计算的长度。应显式加入m_start_page=p_start_page。

页数的区间约定仍须区分:半开区间[start,end)用end-start,首尾页都计入用end-start+1。用半开区间[10,35)、[40,65)构造两篇25页论文,原构造函数会算成35与65,加540页图书得到640;补上起始页赋值后才得到590。若采用含首尾的第10~34、第40~64页,则应同时使用加1的公式。

下方给出明确采用含首尾页码、修正参数拼写和起始页赋值的完整类定义。它是整理示例,不替换上方原题代码;使用时还需由调用方建立集合、创建访问者并调用accept。原解析偶尔写成大写Visitor.visit(this),应使用参数变量visitor。

import java.util.*;

interface LibraryVisitor {

void visit(Book p_book);

void visit(Article p_article);

void printSum();

}

class LibrarySumPrintVisitor implements LibraryVisitor { //打印总页数

private int sum = 0;

public void visit(Book p_book) {

sum = sum + p_book.getNumberOfPages();

}

public void visit(Article p_article) {

sum = sum + p_article.getNumberOfPages();

}

public void printSum(){

System.out.println("SUM = " + sum);

}

}

interface LibraryItemInterface {

void accept(LibraryVisitor visitor);

}

class Article implements LibraryItemInterface{

private String m_title; //论文名

private String m_author; //论文作者

private int m_start_page;

private int m_end_page;

public Article(String p_author, String p_title,int p_start_page,int p_end_page){

m_title=p_title;

m_author= p_author;

m_start_page=p_start_page;
m_end_page=p_end_page;

}

public int getNumberOfPages(){

return m_end_page - m_start_page + 1;

}

public void accept(LibraryVisitor visitor){

visitor.visit(this);

}

}

class Book implements LibraryItemInterface{

private String m_title; //书名

private String m_author; //书作者

private int m_pages; //页教

public Book(String p_author, String p_title,int p_pages){

m_title= p_title;

m_author= p_author;

m_pages= p_pages;

}

public int getNumberOfPages(){

return m_pages;

}

public void accept(LibraryVisitor visitor){

visitor.visit(this);

}

}

评论