一、[材料型]问答题
试题一(15分)
阅读下列说明和图,回答问题1至问题4,将解答填入答题纸的对应栏内。
[说明]
某公司欲开发一款外卖订餐系统,集多家外卖平台和商户为一体,为用户提供在线浏览餐品、订餐和配送等服务。该系统的主要功能是:
1.入驻管理。用户注册:商户申请入驻,设置按时间段接单数量阈值等。系统存储商户/用户信息。
2.餐品管理。商户对餐品的基本信息和优惠信息进行发布、修改、删除。系统存储相关信息。
3.订餐。用户浏览商户餐单,选择餐品及数量后提交订餐请求。系统存储订餐订单。
4.订单处理。收到订餐请求后,向外卖平台请求配送。外卖平台接到请求后发布配送单,由平台骑手接单,外卖平台根据是否有骑手接单返回接单状态。若外卖平台接单成功,系统给支付系统发送支付请求,接收支付状态。支付成功,更新订单状态为已接单,向商户发送订餐请求并由商户打印订单,给用户发送订单状态;若支付失败,更新订单状态为下单失败,向外卖平台请求取消配送,向用户发送下单失败。若系统接到外卖平台返回接单失败或超时未返回接单状态,则更新订单状态为下单失败,向用户发送下单失败。
5.配送。商户备餐后,由骑手取餐配送给用户。送达后由用户扫描骑手出示的订单上的配送码后确认送达,订单状态更改为已送达,并发送给商户。
6.订单评价。用户可以对订单餐品、骑手配送服务进行评价,推送给对应的商户、所在外卖平台,商户和外卖平台对用户的评价进行回复。系统存储评价。
现采用结构化方法对外卖订餐系统进行分析与设计,获得如图1-1所示的上下文数据流图和图1-2所示的0层数据流图。
1、[问题1] (4分)
使用说明中的词语,给出图1-1中实体E1~E4的名称。
参考答案:
E1:商户
E2:外卖平台
E3:用户
E4:支付系统
解析:
本题考察的是采用结构化方法对外卖订餐系统进行分析与设计,主要涉及到数据流图的应用。在上下文中,外部实体为外卖订餐系统提供输入数据流或接收其输出数据流。
对于问题1,我们需要根据说明中的描述来确定图1-1中的实体E1~E4的名称。
E1是商户,因为商户需要入驻申请,管理自己的餐品信息,并接收用户的订餐请求。
E2是外卖平台,因为系统需要向外卖平台请求配送,并且外卖平台会接收配送请求,进行接单操作,并返回接单状态。
E3是用户,因为用户是系统的服务对象,可以浏览商户的餐品、提交订餐请求、对订单进行评价等。
E4是支付系统,因为在流程中,系统需要给支付系统发送支付请求,并接收支付状态来更新订单状态。
因此,根据说明中的描述和数据流图的应用,我们可以确定E1为商户,E2为外卖平台,E3为用户,E4为支付系统。
2、[问题2] (4分)
使用说明中的词语,给出图1-2中的数据存储D1-D4 的名称。
参考答案:
D1:商户/用户信息
D2:订餐订单信息
D3:餐品的基本信息与优惠信息
D4:评价信息
解析:
问题2要求确定图1-2中的数据存储D1-D4的名称。根据说明中的描述和0层数据流图中的信息,可以对应出各数据存储的名称。
- D1:根据说明中用户注册和商户申请入驻时,系统存储商户/用户信息,结合0层数据流图中的D1,可以确定D1为商户/用户信息。
- D2:在订餐过程中,系统存储相关的订餐订单信息,因此D2是订餐订单信息。
- D3:商户发布、修改、删除餐品的基本信息和优惠信息,系统存储这些信息,结合0层图中的P2,可以确定D3为餐品基本信息与优惠信息。
- D4:用户可以对订单进行评价,系统存储这些评价信息,所以D4是评价信息。
3、[问题3] (4分)
根据说明和图中术语,补充图1-2中缺失的数据流及其起点和终点
参考答案:
P3到E3的“餐单”;
P3到P4的“订单请求”;
P4到D2的“订单状态”;
P5到E3的“配送码”
解析:
问题3要求补充图1-2中缺失的数据流及其起点和终点。根据上下文数据流图和0层数据流图,我们需要补充以下数据流:
- P3到E3的数据流“餐单”:在餐品管理阶段,商户需要发布、修改、删除餐品的基本信息和优惠信息,其中“餐单”是一个重要的信息载体,因此需要从P3(商户)流向E3(系统存储相关信息)。
- P3到P4的数据流“订单请求”:在订餐阶段,用户提交订餐请求,系统需要向商户发送订单请求,因此需要从P3(用户)流向P4(系统处理)。
- P4到D2的数据流“订单状态”:在订单处理阶段,系统需要更新订单状态并发送给用户,因此需要从P4(系统)流向D2(用户)。
- P5到E3的数据流“配送码”:在配送阶段,用户需要扫描骑手出示的订单上的配送码以确认送达,因此需要从P5(用户)流向E3(系统记录配送信息)。
以上是根据说明和图中术语对缺失数据流及其起点和终点的补充。
4、[问题4](3分)根据说明,采用结构化语言对“订单处理”的加工逻辑进行描述。
参考答案:
收到订餐请求后,向外卖平台请求配送;
外卖平台接到请求后发布配送单,由平台骑手接单;
外卖平台根据是否有骑手接单返回接单状态;
IF(外卖平台接单成功)THEN{
系统给支付系统发送支付请求,接收支付状态;
IF(支付成功)THEN{
更新订单状态为已接单;
向商户发送订餐请求并由商户打印订单;
给用户发送订单状态;}
ELSE{
更新订单状态为下单失败;
向外卖平台请求取消配送;
向用户发送下单失败;
}ENDIF
}ELSE IF(系统接到外卖平台返回接单失败或超时未返回接单状态)THEN{
更新订单状态为下单失败;
向用户发送下单失败;
}ENDIF
解析:
本题要求使用结构化语言描述“订单处理”的加工逻辑。结构化语言介于自然语言与形式化语言之间,具有控制结构,包括顺序、选择和重复。在描述过程中,采用了祈使语句的自然语言短语,使用了数据字典中的名词和有限的自定义词。根据流程描述,“收到订餐请求”、“向外卖平台请求配送”等是顺序执行的动作,而根据外卖平台接单成功与否以及支付成功与否进行的操作则是选择结构。因此,通过结合顺序和选择结构,对“订单处理”的加工逻辑进行了清晰的结构化描述。
试题二(20分)
按照下列图表,填写答题纸的对应栏内。
【说明】
为了提高接种工作,提高效率,并为了抗击疫情提供疫苗接种数据支撑,需要开发一个信息系统,下述需求完成该系统的数据库设计。
(1)记录疫苗供应商的信息,包括供应商名称、地址和一个电话。
(2)记录接种医院的信息,包括医院名称、地址和一个电话。
(3)记录接种者个人信息,包括姓名、身份证号和一个电话。
(4)记录接种者疫苗接种信息,包括接种医院信息,被接种者信息,疫苗供应商名称和接种日期,为了提高免疫力,接种者可能需要进行多次疫苗接种,(每天最多接种一次,每次都可以在全市任意一家医院进行疫苗接种)。
【概念模型设计】
阶段的信息,设计的实体联系图(不完整)如图2-1所示。

【逻辑结构设计】
根据概念模型设计阶段完成的实体联系图,得出如下关系模式(不完整)
供应商(供应商名称、地址、电话)
医院(医院名称、地址、电话)
供货(供应商名称,(a),供货内容)
被接种者(姓名、身份证号、电话)
接种(接种者身份证号,(b),医院名称、供应商名称)
5、[问题1] (4分)
根据问题描述,补充图2-1的实体联系图(不增加新的实体)。
参考答案:
【问题1】(4分)

解析:
根据题目描述,我们需要设计一个信息系统来管理疫苗接种工作。在概念模型设计阶段,已经给出了实体联系图的一部分,包括供应商、医院和被接种者三个实体。根据题目的要求,我们需要补充实体联系图,以完善逻辑结构设计。
首先,根据题目的描述,“记录接种者疫苗接种信息”包括“接种医院信息,被接种者信息,疫苗供应商名称和接种日期”。这意味着我们需要一个实体来表示“接种记录”,这个实体与“被接种者”、“医院”和“供应商”都存在联系。由于一个被接种者可能进行多次疫苗接种,所以这些联系都是多对多的。
其次,为了记录每一次具体的疫苗接种情况,我们需要在“接种记录”实体中添加属性,包括外键信息(被接种者身份证号、医院名称、供应商名称)以及具体的“接种日期”。这样,我们就可以通过“接种记录”实体来完整地表示每一次疫苗接种的情况。
综上所述,我们补充了实体联系图中的“接种记录”实体,并明确了各实体之间的关系和属性,以完善逻辑结构设计。
6、[问题2] (4分)
补充逻辑结构设计结果中的(a)(b)两处空缺,并标注主键和外健完整性约束。
参考答案:
[问题2](4分)
(a)医院名称
(b)接种日期
供货关系,主键:(供货商名称,医院名称),外键:供货商名称,医院名称;
接种关系,主键:(接种者身份证号,接种日期),外键:接种者身份证号,供应商名称,医院名称。
解析:
根据题目描述和概念模型设计,我们知道“供货”关系需要记录供应商和医院的关联,(a)处应填写与医院相关的内容,故为“医院名称”。而“接种”关系需要记录接种的详细信息,包括接种的日期,所以(b)处应填写“接种日期”。
对于供货关系,主键应能唯一确定一个供货记录,因此选择“供货商名称”和“医院名称”作为主键。同时,供应商和医院的名称需要参照供应商表和医院表,所以这两个字段是外键。
对于接种关系,由于每次疫苗接种都需要记录接种者的身份和接种日期,所以选择“接种者身份证号”和“接种日期”作为主键。而接种者身份证号、供应商名称和医院名称需要参照相应的实体表,因此这些字段是外键。
7、[问题3] (7分)
若医院还兼有核酸检测的业务,检测时可能需要进行多次核酸检测(每天最多检测一次),但每次都可以在全市任意一家医院进行检测。
请在图2-1中增加“被检测者”实体及相应的属性。医院与被检测者之间的“检测”联系及必要的属性,并给出新增加的关系模式。
“被检测者”实体包括姓名。身份证号、地址和一个电话。“检测”联系需要包括检测日期和检测结果等。
参考答案:
新增关系模式
被检测者(身份证号,姓名,地址,电话)
检测(被检测者身份证号,检测日期,医院名称,检测结果)
解析:
根据题目描述,医院除了进行疫苗接种外,还兼有核酸检测的业务。因此,需要在原有的概念模型中增加与核酸检测相关的实体和联系。
- 增加"被检测者"实体:由于被检测者可能进行多次核酸检测,每次检测可能在不同医院进行,所以需要记录被检测者的基本信息。实体包含的属性有:姓名、身份证号、地址和电话。其中,身份证号作为主键,用于唯一标识被检测者。
- 增加"检测"联系:该联系表示医院与被检测者之间的核酸检测关系。联系包含的属性有:检测日期和检测结果。由于一个被检测者可能在多家医院进行多次检测,所以这是一个m:n的关系。
- 在逻辑结构设计阶段,将上述新增的实体和联系转化为关系模式。对于"被检测者"实体,需要记录其基本信息,包括身份证号、姓名、地址和电话。对于"检测"联系,需要记录被检测者的身份证号、检测日期、医院名称和检测结果。为了保持数据的唯一性,可以将被检测者身份证号和检测日期作为该关系模式的主键。
综上所述,按照题目要求完成了概念模型设计和逻辑结构设计的修改,增加了与核酸检测相关的实体和联系,以满足题目的需求。
试题三(20分)
阅读下列说明和图,回答问题1至问题3,将解答填入答题纸的对应栏内。
【说明】
某公司的人事部门拥有一个地址簿(AddressBookSystem),管理系统ddressBookSystem),
于管理公司所有员工的地址记录(PersonAddress)。员工的地址记录包括:姓名、住址、城市、省份、邮政编码以及联系电话等信息。
管理员可以完成对地址簿中地址记录的管理操作,包括:
(1)维护地址记录。根据公司的人员变动情况,对地址记录进行添加、修改、删除等操作;
(2)排序。按照员工姓氏的字典顺序或邮政编码对地址簿的所有记录进行排序。
(3)打印地址记录。以邮件标签的格式打印一个地址簿中的所有记录。为便于管理,管理员在系统中为公司的不同部门建立单独的地址簿。系统会记录管理员对每个地址簿的修改操作,包括:
(1)创建地址簿。新建个地址簿并保存。
(2)打开地址簿。打开一个已有的地址簿。
(3)修改地址簿。对打开的地址簿进行修改并保存。
系统将提供一个GUI(图形用户界面)实现对地址簿的各种操作。
现采用面向对象方法分析并设计该地址簿管理系统,得到如图3-1所示的用例图和图3-2所示的类图。
8、[问题1](6分)
根据说明中的描述,给出图3-1中U1~U6所对应的用例名。
参考答案:
U1:按字典排序;
U2:按邮政编码排序
U3:创建地址簿
U4:修改地址簿
U5:打开地址簿
U6:保存
(U1与U2可互换)
解析:
本题考察面向对象设计方法与应用。对于问题1,根据说明中的描述和UML用例图的定义,参与者与系统的交互通过用例来实现。通过对题目给出的需求描述结合用例图,我们可以得出以下结论:
U1与U2与用例“排序”有关。根据描述(2)需要按照员工姓氏的字典顺序或邮政编码对地址簿的所有记录进行排序,因此U1为按姓氏字典顺序排序,U2为按邮政编码排序。由于这两种排序方式可以互换,所以U1与U2的顺序可以调整。
对于其他需求描述,如“创建地址簿”、“打开地址簿”、“修改地址簿”以及“保存”,我们可以直接根据操作命名相应的用例。因此,U3为创建地址簿,U4为修改地址簿,U5为打开地址簿,U6为保存。
9、[问题2](5分)
根据说明中的描述,给出图3-2中类AddressBook的主要属性和方法以及类Pernoddress的主要属性(可以使用说明中的文字)。
参考答案:
AddressBook,属性:部门编号,姓名、住址、城市、省份、邮政编码以及联系电话;
AddressBook方法:添加、创建、打开、修改、删除,保存等
PersonAddress属性:姓名、住址、城市、省份、邮政编码、联系电话。
解析:
根据题目描述,类PersonAddress代表员工的地址记录,因此其主要属性应包括员工的姓名、住址、城市、省份、邮政编码和联系电话等信息。
类AddressBook代表地址簿,用于管理公司所有员工的地址记录。除了员工地址记录的信息,还需要包括部门信息,因此其主要属性应有部门编号。同时,根据题目描述,管理员可以对地址簿进行添加、修改和删除地址记录的操作,因此类AddressBook的方法应包括这些操作。另外,管理员还可以创建新的地址簿、打开已有的地址簿以及修改打开的地址簿,所以类AddressBook的方法还应包括创建、打开和保存。
10、[问题3](4分)
根据说明中的描述以及图3-1所示的用例图,请说明《include》关系和《extend》关系的含义是什么?
参考答案:
extend表示的是扩展关系。描述为:如果一个用例明显地混合了两种或两种以上的不同场景,即根据情况可能会发生多种分支,则可以将这个用例分为一个基本用例和一个或多个扩展用例,关系图示指向为扩展用例指向基本用例。
include表示的是包含关系。描述为:当可以从两个或两个以上用例中提取公共行为的时候,应该使用包含关系来表示它们。其中这个提取出来的公共用例称之为抽象用例,而把原始用例称为基本用例和扩展用例。
解析:
本题考察的是面向对象设计中的用例图中的include关系和extend关系的含义。
include关系表示包含关系,主要用于提取两个或多个用例中的公共行为,将其定义为抽象用例,而原始用例则被称为基本用例和扩展用例。这种关系用于表示某些功能或行为是某些用例所共有的,可以将其独立出来,以便于管理和复用。
extend关系表示扩展关系,用于处理一个用例中混合了多种场景的情况。当一个用例根据其不同的条件可能展现出不同的行为时,可以将这个用例分为一个基本用例和若干个扩展用例。在关系图中,扩展用例是指向基本用例的。这样,可以根据具体的条件执行不同的扩展用例,从而丰富和扩展基本用例的功能。
在地址簿管理系统的设计中,这两种关系有助于更好地组织和描述系统的功能需求,提高系统的可维护性和可扩展性。
试题四(15分)
阅读下列说明和C代码,回答问题1至问题3,将解答写在答题纸的对应栏内。
【说明】
某工程计算中经常要完成多个矩阵相乘(链乘)的计算任务,对矩阵相乘进行以下说明。
(1)两个矩阵相乘要求第一个矩阵的列数等于第二个矩阵的行数,计算量主要由进行乘法运算的次数决定,假设采用标准的矩阵相乘算法,计算Amxn*Bnxp需要m*n*p次行乘法运算的次数决定、乘法运算,即时间复杂度为O(m*n*p)。
(2)矩阵相乘满足结合律,多个矩阵相乘时不同的计算顺序会产生不同的计算量。以矩阵A15×100,A2100*8,A38x50三个矩阵相乘为例,若按(A1*A2)*A3计算,则需要进行5*100*8+5*8*50=6000次乘法运算,若按A1*(A2*A3)计算,则需要进行100*8*50+5*10
0*50=65000次乘法运算。
矩阵链乘问题可描述为:给定n个矩阵,对较大的n,可能的计算顺序数量非常庞大,用蛮力法确定计算顺序是不实际的。经过对问题进行分析,发现矩阵链乘问题具有最优子结构,即若A1*A2**An的一个最优计算顺序从第k个矩阵处断开,即分为A1*A2*…*Ak和Ak+1*Ak+2*...*An两个子问题,则该最优解应该包含A1*A2*…*Ak的一个最优计算顺序和Ak+1*Ak+2*...*An的一个最优计算顺序。据此构造递归式,

其中,cost[i][j]表示Ai+1*Ai+2*...Aj+1的最优计算的计算代价。最终需要求解cost[0][n-1]。
【C代码】
算法实现采用自底向上的计算过程。首先计算两个矩阵相乘的计算量,然后依次计算3个矩阵、4个矩阵、…、n个矩阵相乘的最小计算量及最优计算顺序。下面是该算法的语言实现。
(1) 主要变量说明
n:矩阵数
seq[]:矩阵维数序列
cost[i][j]:二维数组,长度为n*n,其中元素cost[i][j]表示Ai+1*Ai+2**Aj+1的最优的计算代价。
trace[][]:二维数组,长度为n*n,其中元素trace[i][j]表示Ai+1*Ai+2**Aj+1的最优计算顺序对应的划分位置,即k。
(2)函数cmm
#define N100
int cost[N[N];
int trace[N][N];
int cmm(int n,int seq[]){
int tempCost;
int tempTrace;
int i,j,k,p;
int temp;
for( i=0;i<n;i++){
cost[i][i] = 0;
}
for(p=1;p<n;p++){
for(i=0; i<n-p;i++){
(1);
tempCost = -1;
for(k = i;(2);k++){
temp=(3);
if(tempCost==-1 || tempCost>temp){
tempCost = temp;
tempTrace=k;
}
}
cost[i][j] = tempCost;
(4);
}
}
return cost[0][n-1];
}
11、[问题1](8分)
根据以上说明和C代码,填充C代码中的空(1)~(4)。
参考答案:
(1) j=i+p
(2) k<j
(3) cost[i][k]+cost[k+1][j]+seq[i]*seq[k+1]*seq[j+1]
(4) trace[i][j] = tempTrace
解析:
本题考查矩阵连乘最优调度问题,是一种动态规划算法。
问题1:
1.上述算法中,第一循环是给n个cost[i][j]赋初值0;第二个循环是外循环,其循环变量P表示矩阵连乘的规模。当P=1时,算法会计算出所有规模为2的cost[i][i+1],当P=2时,会计算出所有规模为3的cost[i][i+2],以此类推。最终计算出的结果就是我们所求的cost[1][n-1],所以(1)填写i < n-p;
2. 第三个循环是内循环,其循环变量i表示矩阵连乘的起始位置,即从单个矩阵开始,逐渐增加矩阵的数量进行计算,直到包含所有矩阵的连乘。所以(2)填写j=i+p;
3. 第四个循环用于计算从位置i到位置j之间的矩阵连乘的最小代价,是通过遍历所有可能的分割点k来得到的。所以(3)填写cost[i][k] + cost[k+1][j] + seq[i]*seq[k+1]*seq[j+1],这表示从位置i到位置j的矩阵连乘代价等于从位置i到位置k的矩阵连乘代价加上从位置k+1到位置j的矩阵连乘代价,再加上这三个矩阵直接相乘的代价。
4. 当找到最优的计算顺序和对应的代价后,需要记录这个最优计算顺序的划分位置,即哪个矩阵是分割点。所以将这个位置记录到trace数组中,即trace[i][j] = tempTrace。
12、[问题2](4分)
根据以上说明和C代码,该问题采用了(5)算法设计策略,时间复杂度为(6)(用O符号表示)。
参考答案:
问题2:
(5)动态规划
(6)O(n^3)
解析:
根据题目描述和C代码,该问题采用了动态规划的算法设计策略。动态规划是一种通过分解问题并寻找子问题的最优解来解决复杂问题的算法设计策略。在这个问题中,通过构建cost数组和trace数组来记录矩阵链乘的最优计算代价和计算顺序,采用自底向上的计算过程,逐步求解更大规模问题的最优解。
关于时间复杂度,根据解析中的描述,算法中的第3行循环(即求解最优解的循环)需要执行n-1次,每次循环中需要执行一次比较操作来确定最优解。而第2行的外循环从1到n-1,因此整个算法的时间复杂度为O(n^3)。这是因为总共有三个嵌套的循环,每个循环的复杂度分别为n、n-1和n,所以整体的时间复杂度为O(n^3)。
13、[问题3](3分)
考虑实例n=4,各个矩阵的维数为A1为15*5,A2为5*10,A3为10*20,A4为20*25,即维度序列为15,5,10,20和25。则根据上述C代码得到的一个最优计算顺序为(7)(用加括号方式表示计算顺序),所需要的乘法运算次数为 (8)。
参考答案:
【问题3】 (3分)
(7)A1*((A2*A3)*A4)
(8)5375
解析:
:根据说明中的矩阵链乘问题和C代码的描述,对于给定的矩阵维度序列(A1为155,A2为510,A3为1020,A4为2025),我们需要找到最优的计算顺序和对应的乘法运算次数。
计算顺序可以通过尝试不同的组合来确定,包括A1A2A3*A4、(A1 (A2 (A3A4 )))、((A1A2 )(A3A4 ))等。通过计算每种组合的开销(即乘法运算次数),我们可以找到开销最小的计算顺序。
在这个例子中,计算顺序为A1((A2A3)A4)时,乘法运算次数最小,为5375。这是因为这种计算顺序能够最大程度地减少乘法运算的次数,根据矩阵乘法的规则,我们可以通过合理地组织计算顺序来降低计算复杂度。
二、问答题
14、试题五(15分)
阅读下列说明和C++代码。将应填入(n)处的字句写在答题纸的对应栏内。
【说明】
在软件系统中,通常都会给用户提供取消、不确定或者错误操作的选择,允许将系统恢复到原先的状态。现使用备忘录(Memento)模式实现该要求,得到如图 5-1 所示的类图。Memcnto 包含了要被恢复的状态。Originator创建并在 Memento 中存储状态。Caretaker 负责从 Memento 中恢复状态。
【C++代码】
#include <iostream>
#include <string>
#inchude <vector>
using namespace std;
class Memento {
private:
string state;
public:
Memento(string state){ this->state = state; }
String getState( ) { return state; }
public:
void setState(string state)(this>sate-state;string getStateO{retumn state;}Memento saveStateToMemento0){
return (1)
void getStateFromMemento(Memento Memento){
state= (2)
class CareTaker{
private :
vector<Memento> mementoList;
pubilc:
void (3) { mementoL ist.push back(state)
(4) ;return mementoList(index];}
int mian(){
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 save State "<<"+"<< originator>getState()<<endl;return 0;}
参考答案:
【参考答案】:
(1)new Memento(state)
(2)Memento->getState()
(3)virtual void add(Memento * state)
(4)Memento get(int index)
(5)originator->saveStateToMemento()
(6)originator->saveStateToMemento()
解析:
这是一道关于备忘录模式实现的编程题目。备忘录模式是一种行为型设计模式,主要用于在不破坏封装的前提下捕获对象的内部状态并在对象之外保存这个状态,以便以后可以将对象恢复到原先保存的状态。
对于这道题目,我们需要根据提供的说明和C++代码,将应填入(n)处的字句写出。
解析如下:
- 在类Originator中创建记录自身保存状态的备忘录,在方法saveStateToMemento()中返回Memento类型的备忘录,所以(1)处为new Memento(state);
- 在getStateFromMemento(Memento Memento)方法中获取备忘录Memento的状态,所以调用Memento的getState(),所以(2)为Memento->getState();
- 在备忘录管理员Caretaker中,(3)和(4)需要补充方法名。结合题目描述和代码,需要在列表mementoList中添加Memento类对象,所以(3)是virtual void add(Memento *state);结合类Memento的使用,所以(4)是Memento get(int index);
- (5)和(6)都是需要在careTaker存储发起人创建的备忘录,因此都是originator->saveStateToMemento()。
综上,答案为(1)new Memento(state);(2)Memento->getState();(3)virtual void add(Memento *state);(4)Memento get(int index);(5)originator->saveStateToMemento();(6)originator->saveStateToMemento()。
15、试题六(15分)
阅读下列说明和Java代码,将应填入(n)处的字句写在答题纸的对应栏内。
【说明】
在软件系统中,通常都会给用户提供取消、不确定或者错误操作的选择,允许将系统恢复到原先的状态。现使用备忘录(Memento)模式实现该要求,得到如图6-1所示的类图。Memento 包含了要被恢复的状态。Originator创建并在 Memento 中存储状态。Caretaker 负责从 Memento 中恢复状态。

【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 ListmementoList= new ArrayList();
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("CurrentState"+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()
解析:
这道题考察的是备忘录模式的应用。在备忘录模式中,发起人(Originator)创建并存储状态到备忘录(Memento)中,备忘录管理员(Caretaker)负责从备忘录中恢复状态。
对于第一空,因为需要创建一个新的备忘录来存储状态,所以填写new Memento(state)。
对于第二空,从备忘录中获取状态,应调用备忘录的getState()方法,所以填写memento.getState()。
第三空和第四空是在Caretaker类中添加方法和获取备忘录的方法,根据代码逻辑,添加方法应该为void add(Memento state)(或 void add(Memento memento)),获取方法应该为Memento get(int index)(或 Memento get(index))。
第五空和第六空都是在main方法中创建并存储备忘录的,所以应该填写originator.saveStateToMemento()。
喵呜刷题:让学习像火箭一样快速,快来微信扫码,体验免费刷题服务,开启你的学习加速器!