乐于分享
好东西不私藏

软件设计师-2019年下半年案例分析真题解析【下篇】

软件设计师-2019年下半年案例分析真题解析【下篇】
【第 1 题】(题型:简答题)
题目:
阅读下列说明和数据流图,回答问题 1 至问题 4, 将解答填入答题纸的对应栏内。
【说明】
某公司欲开发一款二手车物流系统,以有效提升物流成交效率。该系统的主要功能是:
(1) 订单管理:系统抓取线索,将车辆交易系统的交易信息抓取为线索。帮买顾问看到有买车线索后,会打电话询问买家是否需要物流,若需要,帮买顾问就将这个线索发起为订单并在系统中存储,然后系统帮助买家寻找物流商进行承运。
(2) 路线管理:帮买顾问对物流商的路线进行管理,存储的路线信息包括路线类型、物流商、起止地点。路线分为三种,即固定路线、包车路线、竞拍体系,其中固定路线和包车路线是合约制。包车路线的发车时间由公司自行管理,是订单的首选途径。
(3) 合约管理:帮买顾问根据公司与物流商确定的合约,对合约内容进行设置,合约信息包括物流商信息、路线起止城市、价格、有效期等。
(4) 寻找物流商:系统根据订单的类型 (保卖车、全国购和普通二手车)、起止城市、需要的服务模式 (买家接、送到买家等) 进行自动派发或以竞拍体系方式选择合适的物流商。即:有新订单时,若为保卖车或全国购,则直接分配到竞拍体系中;否则,若符合固定路线和 / 或包车路线,系统自动分配给合约物流商,若不符合固定路线和包车路线,系统将订单信息分配到竞拍体系中。竞拍体系接收到订单后,将订单信息推送给有相关路线的物流商,物流商对订单进行竞拍出价,最优报价的物流商中标。最后,给承运的物流商发送物流消息,更新订单的物流信息,给车辆交易系统发送物流信息。
(5) 物流商注册:物流商账号的注册开通。
现采用结构化方法对二手车物流系统进行分析与设计,获得如图 1-1 所示的上下文数据流图和图 1-2 所示的 0 层数据流图。
【问题 1】(3 分)
使用说明中的词语,给出图 1-1 中的实体 E1~E3 的名称。
【问题 2】(5 分)
使用说明中的词语,给出图 1-2 中的数据存储 D1~D5 的名称。
【问题 3】(4 分)
根据说明和图中术语,补充图 1-2 中缺失的数据流及其起点和终点。
【问题 4】(3 分)
根据说明,采用结构化语言对 “P5: 寻找物流商” 的加工逻辑进行描述。
【 答 案 】
【问题 1】
E1:帮买顾问   E2:车辆交易系统   E3:物流商
【解析】
根据上下文数据流图的交互关系:
E1 与系统交互物流合约、路线信息、订单信息,对应说明中的 "帮买顾问" 角色;
E2 向系统提供交易线索、车辆交易信息,接收系统的物流信息,对应说明中的 "车辆交易系统";
E3 向系统发送竞拍出价、物流商注册信息,接收物流消息,对应说明中的 "物流商"。
【问题 2】
D1:线索表(或线索存储)
D2:订单表(或订单信息存储)
D3:路线表(或路线信息存储)
D4:合约表(或合约信息存储)
D5:物流消息表(或物流消息存储)
【解析】
根据 0 层数据流图的加工与存储的交互:
P1(抓取线索)向 D1 写入数据,D1 向 P2(发起订单)提供数据,对应说明中的 "线索" 存储;
P2(发起订单)向 D2 写入数据,对应说明中的 "订单信息" 存储;
P3(路线管理)向 D3 读写数据,对应说明中的 "路线信息" 存储;
P4(合约管理)向 D4 读写数据,对应说明中的 "合约信息" 存储;
P5(寻找物流商)向 D5 写入数据,对应说明中的 "物流消息" 存储。
【问题 3】
数据流名称
起点
终点
新订单
P2(发起订单)
P5(寻找物流商)
物流信息
P5(寻找物流商)
E2(车辆交易系统)
合约信息
D4(合约表)
P5(寻找物流商)
路线信息
D3(路线表)
P5(寻找物流商)
【解析】
对照说明和 0 层数据流图,缺失的关键数据流包括:
P2 生成新订单后需要传递给 P5 进行物流商匹配;
P5 需要向车辆交易系统返回物流信息;
P5 需要读取合约信息来判断合约物流商;
P5 需要读取路线信息来判断是否符合固定 / 包车路线。
【问题 4】
    IF 订单类型为保卖车 或 订单类型为全国购
    THEN 将订单分配到竞拍体系
    ELSE
        IF 订单符合固定路线 或 订单符合包车路线
        THEN 将订单自动分配给合约物流商
        ELSE
            将订单分配到竞拍体系
        ENDIF
    竞拍体系将订单信息推送给有相关路线的物流商,接收物流商的竞拍出价,选择最优报价的物流商中标
    ENDIF
    给中标的物流商发送物流消息,更新订单的物流信息
【解析】
严格按照说明中的逻辑进行结构化描述,分层次处理订单类型判断、路线匹配判断,以及竞拍体系的处理流程。
【第 2 题】(题型:简答题)
题目:
阅读下列说明,回答问题 1 至问题 4, 将解答填入答题纸的对应栏内。
【说明】
某公司拟开发一套新入职员工的技能培训管理系统,以便使新员工快速胜任新岗位。该系统的部分功能及初步需求分析的结果如下所述:
【需求分析结果】
(1) 部门信息包括部门号、名称、部门负责人、电话等,部门号唯一标识部门关系中的每一个元组, 一个部门有多个员工,但一名员工只属于一个部门;每个部门只有一名负责人,负责部门工作。
(2) 员工信息包括员工号、姓名、部门号、岗位、基本工资、电话、家庭住址等,其中员工号是唯一标示员工关系中的每一个元组;岗位有新入职员工、培训师、部门负责人等;不同的岗位设置不同的基本工资。新入职员工要选择多门课程进行培训,并通过考试取得课程的成绩。 一名培训师可以讲授多门课程, 一门课程可以由多名培训师讲授。
(3) 课程信息包括课程号、课程名称、学时等,其中课程号唯一标识课程关系的每一个元组。
【概念模型设计】
根据需求阶段收集的信息,设计的实体联系图 (不完整) 如图 2- 1 所示。
【逻辑结构设计】
根据概念模型设计阶段完成的实体联系图,得出如下关系模式 (不完整):
部门 (部门号,部门名,部门负责人,电话)
员工 (员工号,姓名,部门号,   (d)   , 电话,家庭住址)
课程 (     (e)     , 课程名称,学时)
讲授 (课程号,培训师,培训地点)
培训 (课程号,     (f)    )
【问题 1】(5 分)
(1) 补充图 2-1 中的空 (a)~(c)。
(2) 图 2-1 中是否存在缺失联系,若存在,则说明所缺失的联系和联系类型。
【问题 2】(3 分)
根据题意,将关系模式中的空 (d)~(f) 补充完整。
【问题 3】(5 分)
(1) 员工关系模式的主键为    (g)    , 外键为    (h)     ;
(2) 讲授关系模式的主键为    (i)     , 外键为    (i)    
【问题 4】(2 分)
员工关系是否存在传递依赖?用 100 字以内的文字说明理由。
【 答 案 】
【问题 1】
(a):1(或一对一)
(b):1(或一对多)
(c):成绩(或培训成绩)
【解析】
(1) 部门和负责人是一对一关系(一个部门只有一名负责人),所以 (a) 为 1;培训师和课程的讲授关系是一对多(一名培训师可以讲授多门课程),所以 (b) 为 1;培训联系需要记录成绩,所以 (c) 为成绩。
(2) 需求中新入职员工需要选择多门课程培训并取得成绩,所以员工和课程之间存在多对多的培训联系,且包含成绩属性。
【问题 2】
(d):岗位,基本工资
(e):课程号
(f):员工号,成绩
【解析】
(d) 根据员工信息需求,需要补充岗位和基本工资;(e) 课程关系的主键是课程号;(f) 培训关系需要关联员工号和记录成绩。
【问题 3】
(g):员工号;(h):部门号
(i):课程号,培训师;外键:课程号,培训师(培训师对应员工号)
【解析】
(1) 员工关系的主键是员工号,部门号是引用部门关系的外键;(2) 讲授关系的主键是课程号和培训师的组合,两者分别是课程和员工关系的外键。
【问题 4】
存在传递依赖。因为员工的岗位决定基本工资,而岗位依赖于员工号,所以存在 "员工号→岗位→基本工资" 的传递函数依赖。
【解析】
根据函数依赖的定义,若 A→B 且 B→C,则 A→C 为传递依赖。员工号决定岗位,岗位决定基本工资,因此存在传递依赖。
【第 3 题】(题型:简答题)
题目:
阅读下列说明和 UML 图,回答问题 1 至问题 3, 将解答填入答题纸的对应栏内。
【说明】
某牙科诊所拟开发一套信息系统,用于管理病人的基本信息和就诊信息。诊所工作人员包括:医护人员 (DentalStaff)、接待员 ( Receptionist) 和办公人员 (OfficeStaff) 等。系统主要功能需求描述如下:
记录病人基本信息 (Maintain patient info)。初次就诊的病人,由接待员将病人基本信息录入系统。病人基本信息包括病人姓名、身份证号、出生日期、性别、首次就诊时间和最后一次就诊时间等。每位病人与其医保信息 ( Medicallnsurance ) 关联。
记录就诊信息 (Record office visit info)。病人在诊所的每一次就诊,由接待员将就诊信息 ( Office Visit) 录入系统。就诊信息包括就诊时间、就诊费用、支付代码、病人支付费用和医保支付费用等。
记录治疗信息 (Record dental procedure)。病人在就诊时,可能需要接受多项治疗,每项治疗 ( Procedure ) 可能由多位医护人员为其服务。治疗信息包括:治疗项目名称、治疗项目描述、治疗的牙齿和费用等。治疗信息由每位参与治疗的医护人员分别向系统中录入。
打印发票 (Print invoices)。发票 (Invoice) 由办公人员打印。发票分为两种:给医保机构的发票 ( Insurancelnvoic e ) 和给病人的发票 ( PatientInvoice )。两种发票内容相同,只是支付的费用不同。当收到治疗费用后,办公人员在系统中更新支付状态 (Enterpayment )。
记录医护人员信息 (Maintain dental staff info)。办公人员将医护人员信息录入系统。医护人员信息包括姓名、职位、身份证号、家庭住址和联系电话等。
医护人员可以查询并打印其参与的治疗项目相关信息 ( 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 和 DentalStaff 的必要属性。
【 答 案 】
【问题 1】
A1:接待员(Receptionist)
A2:医护人员(DentalStaff)
A3:办公人员(OfficeStaff)
U1:记录就诊信息(Record office visit info)
U2:记录病人基本信息(Maintain patient info)
U3:打印发票(Print invoices)
【解析】
本问题给出的应用场景是一个用于管理病人基本信息和就诊信息的牙科诊所信息系统。
本问题要求补充用例图。用例图展现了一组用例、参与者以及它们之间的关系。用例建模是按照业务事件、谁发起事件,以及系统如何响应事件建模系统功能的过程。
参与者表示需要与系统交互以交换信息的任何事物。参与者可以是一个用户,可以是外部系统的一个角色,也可以是一个人。从题目的说明中可以很容易地发现,该系统中有 3类与系统交互的角色:医护人员、接待员和办公人员。根据说明所描述的每个角色所参与的功能,可以判断出:A1对应的参与者是接待人员、A2对应的参与者是医护人员、A3对应的参与者是办公人员。
用例是一组相关行为的自动的和手动的步骤序列,其目的是完成单个业务任务。下面需要确定与参与者A1(接待人员)相关联的用例。根据说明可知,A1参与或激发的用例包括:记录病人基本信息和记录就诊记录,所以用例U1和U2分别对应“记录病人基本信息”和“记录就诊记录”。U3是与参与者 A3(办公人员)相关联的用例。根据说明可知,A3参与或激发的用例包括:打印发票、更新支付状态和记录医护人员信息。显而易见,U3应该对应着用例“打印发票”。
【问题 2】
C1:PatientInvoice
C2:InsuranceInvoice
C3:Invoice
C4:Procedure
C5:OfficeVisit
【解析】
本问题要求将图3-2 所示的类图补充完整。
首先观察该类图,发现在图中存在一个继承结构:C3为基类、C1和C2为派生类。而这3个类又分别与类 Payment、MedicalInsurance 相关联,这两个类实现的都是与支付相关的功能。从说明中关于支付相关功能的描述可知,“发票分为两种:给医保机构的发票(InsuranceInvoice)和给病人的发票(PatientInvoice)",这是一种明显的“一般——特殊”关系,这种关系在面向对象中通常采用继承机制来描述。表达一般概念的实体作为基类,特殊概念的实体作为派生类。由此可以确定C3对应类 Invoice。C1关联着类 Patient,所以C1对应类PatientInvoice,C2对应类 Insurancelnvoice。
C4、C5 及其相关联的类,对应的是该系统维护就诊信息和治疗信息的功能。由说明可知,病人可以多次就诊;病人的每次就诊,可能包含多项治疗。这个需求由类Patient、C5 及 C4 构成的关联结构表达。由此推断出,C5 对应着类 OfficeVisit,C4 对应着类Procedure。
【问题 3】
C4的属性:治疗项目名称、治疗项目描述、治疗的牙齿、费用。
C5的属性:就诊时间、就诊费用、支付代码、病人支付费用、医保支付费用。
Patient 的属性:病人姓名、身份证号、出生日期、性别、首次就诊时间、最后一次
就诊时间。
DentalStaff 的属性:姓名、职位、身份证号、家庭住址、联系电话。
【解析】
根据需求中的信息提取必要属性,每个类的属性需要满足唯一标识和业务需求的基本信息。
【第 4 题】(题型:填空题 + 简答题)
题目:
阅读下列说明和 C 代码,回答问题 1 至问题 3, 将解答填入答题纸的对应栏内。
【说明】
0-1 背包问题定义为:给定 i 个物品的价值 v [1…i]、重量 w [1…i] 和背包容量 T, 每个物品装到背包里或者不装到背包里。求最优的装包方案,使得所得到的价值最大。
0-1 背包问题具有最优子结构性质。定义 c [i [T] 为最优装包方案所获得的最大价值,则可得到如下所示的递归式。
【C 代码】
下面是算法的 C 语言实现。
(1) 常量和变量说明
T: 背包容量
v []: 价值数组
w []: 重量数组
c [][]:c [i][j] 表示前 i 个物品在背包容量为 j 的情况下最优装包方案所能获得的最大价值
(2) C 程序
#include<stdio.h>#include<math.h>#define N 6#define maxT 1000int c[N] [maxT]={0};  intMemoized Knapsack(int v[N], int w[N], intT){    int i;    int j;    for(i= 0;i< N;i++){      for(j= 0;j <= T;j++){        c[i][j] = -1;      }    }    returnCalculate_Max_Value(v,w,N-1,T);}intCalculate_Max_Value(int v[N], int w[N],inti,int j){  int temp = 0;  if(c[i][j]!= -1){    return (1) ;  }  if(i== 0 ll j == 0){    c[i][j] = 0;  }else{    c[i][j]= Calculate_Max_Value(v,w,i-1,j);    if( (2) ){      temp =(3) ;       if(c[i][j] < temp){        (4) ;      }    }  }  return c[i][j];}
【问题 1】(8 分)
根据说明和C 代码,填充 C 代码中的空 (1)~(4)。
【问题 2】(4 分)
根据说明和 C 代码,算法采用了_ (5) 设计策略。在求解过程中,采用了_ (6) (自底向上或者自顶向下) 的方式。
【问题 3】(3 分)
若 5 项物品的价值数组和重量数组分别为 v []={0,1,6,18,22,28} 和 w []={0,1,2,5,6,7} 背包容量为 T=11, 则获得的最大价值为 (7) 。
【 答 案 】
【问题 1】
(1) c [i][j]
(2) j >= w [i]
(3) Calculate_Max_Value (v,w,i-1,j-w [i]) + v [i]
(4) c [i][j] = temp
【解析】
(1) 当 c [i][j] 已经计算过(不为 - 1),直接返回缓存的值;
(2) 判断当前物品的重量是否小于等于背包剩余容量;
(3) 计算放入当前物品后的价值,即剩余容量的最优价值加上当前物品的价值;
(4) 如果放入当前物品的价值更大,则更新 c [i][j] 的值。
【问题 2】
(5) 动态规划(或备忘录法)
(6) 自顶向下
【解析】
该算法采用了动态规划的备忘录方法,通过递归从顶部问题(n 个物品,容量 T)逐步分解为子问题求解,属于自顶向下的方式。
【问题 3】
(7) 40
【解析】
通过动态规划计算,选择价值为 18(重量 5)、22(重量 6)的物品,总重量 5+6=11,总价值 18+22=40,为最优解。
【第 5 题】(题型:填空题)
题目:
阅读下列说明和 C++ 代码,将应填入 (n) 处的字句写在答题纸的对应栏内。
【说明】
某文件管理系统中定义了类 OfficeDoc 和 DocExplorer。当类 OfficeDoc 发生变化时,类 DocExplorer 的所有对象都要更新其自身的状态。现采用观察者 (Observer ) 设计模式 来实现该需求,所设计的类图如图 5-1 所示。
【C+ + 代码】
#include<iostream>#include<vector>#include<string>using namespace std;class Observer {  public :    (1) ;};class Subject {protected :  vector<_(2) >myObs;public :  virtualvoidAttach(Observer *obs){myObs.push_back(obs);}  virtualvoidDetach(Observer *obs){  for(vector<Observer*>::iterator iter =myObs.begin();    iter !=myObs.end();iter ++){    if(*iter ==obs){myObs.erase(iter);return;}  }  }  virtualvoidNotify(){    for(vector<Observer*>::iterator iter =myObs.begin();      iter !=myObs.end();iter ++){      (3) ;    }  }virtualintgetStatus()=0;virtualvoidsetStatus(int status)=0;};class OfficeDoc:public Subject {private :  string mySubjectName;  int m_status;public:  OfficeDoc(string name):mySubjectName(name),m_status(0){}  voidsetStatus(int status){m_status =status;}  intgetStatus(){return m_status;}};class DocExplorer :public Observer {private :  string myObsName;public :DocExplorer(string name, (4) sub):myObsName(name){sub-> (5) ;}  voidupdate(){cout <<"update observer:"<<myObsName <<endl;}};intmain(){  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)
【解析】
(1) Observer 类是抽象类,需要定义纯虚函数 update ();
(2) Subject 维护的观察者列表是 Observer 指针的向量;
(3) Notify () 方法需要调用每个观察者的 update () 方法;
(4) DocExplorer 的构造函数需要接收 Subject 指针;
(5) DocExplorer 构造时需要将自身注册到 Subject 的观察者列表中。
【第 6 题】(题型:填空题)
题目:
阅读下列说明和 Java 代码,将应填入 (n) 处的字句写在答题纸的对应栏内。
【说明】
某文件管理系统中定义了类 OfficeDoc 和 DocExplorer。当类 OfficeDoc 发生变化时,类 DocExplorer 的所有对象都要更新其自身的状态。现采用观察者 (Observer ) 设计模式 来实现该需求,所设计的类图如图 6-1 所示。
【Java 代码】
import java.util.*;interface Observer {  public (1) ;}interface Subject {  publicvoidAttach(Observer obs);  publicvoidDetach(Observer obs);  publicvoidNotify();  publicvoidsetStatus(int status);  publicintgetStatus();}class OfficeDoc implements Subject {  private List<(2) >myObs;  private String mySubjectName;  private int m_status;  publicOfficeDoc(String name){    mySubjectName =name;    this.myObs =new ArrayList<Observer>();    m_status =0;  }  publicvoidAttach(Observer obs){this.myObs.add(obs);}  publicvoidDetach(Observer obs){this.myObs.remove(obs);}  publicvoidNotify(){  for(Observer obs:this.myObs){  (3);  }  }  publicvoidsetStatus(int status){    m_status =status;    System.out.println("Setstatus subject["+mySubjectName +"]status:"+status);  }  publicintgetStatus(){return m_status;}}class DocExplorer implements Observer {  private String myObsName;  publicDocExplorer(String name, (4) sub){    myObsName =name;    sub. (5);  }publicvoidupdate(){  System.out.println("update observer["+myObsName +"]");}}class ObserverTest {  publicstaticvoidmain(String[]args){    Subject subjectA =new OfficeDoc("subject A");    Observer observerA=new DocExplorer("observer A",subjectA);    subjectA.setStatus(1);    subjectA.Notify();  }}
【 答 案 】
(1) void update ();
(2) Observer
(3) obs.update ();
(4) Subject
(5) Attach (this)
【解析】
(1) Observer 接口需要定义 update () 方法;
(2) Subject 维护的观察者列表是 Observer 类型的 List;
(3) Notify () 方法需要调用每个观察者的 update () 方法;
(4) DocExplorer 的构造函数需要接收 Subject 类型的参数;
(5) DocExplorer 构造时需要将自身注册到 Subject 的观察者列表中。
知识点盘点:
【试题一知识点】
・数据流图(DFD)的基本构成:实体、加工、数据存储、数据流
・上下文数据流图与 0 层数据流图的对应关系
・结构化语言的描述规范
・结构化分析方法的核心思想
【试题二知识点】
・实体联系图(ER 图)的设计与补充
・关系模式的转换规则
・主键、外键的识别与设计
・函数依赖与传递依赖的判断
・数据库逻辑结构设计方法
【试题三知识点】
【知识点】
・UML 用例图的参与者与用例识别
・UML 类图的类识别与关联关系分析
・面向对象分析中的类属性提取
・需求到 UML 模型的转换方法
【试题四知识点】
・0-1 背包问题的动态规划解法
・备忘录法的实现原理
・自顶向下与自底向上的动态规划区别
・动态规划的最优子结构性质
【试题五知识点】
【知识点】
・观察者设计模式的原理与实现
・C++ 抽象类与纯虚函数的使用
・容器类(vector)的使用
・面向对象的多态性实现
【试题六知识点】
・Java 接口的定义与实现
・观察者设计模式的 Java 实现
・泛型集合(List、ArrayList)的使用
・面向对象的多态性在 Java 中的实现

THE  END -

点击下方卡片关注我   点个小赞你必上岸↓↓↓

 点个小“赞” 你必上岸