面向对象分析和设计课程报告任务书2020

来源:新东方在线 发布时间:2020-08-23 点击:

  面向对象技术的应用 --课程报告

 课程名称:面向对象分析与设计 课程类别:专业主干课 开课学期:2019 秋季学期

  编 写 单 位:

 信 息 工 程 学 院

 报 告 完 成 人:

 王智厚 学 号 :

  1004176115 指 导 教 师 :

  曾 姗 提 交 班 级 :

  软件一班 提 交 时 间 :

 2019.12.22

 《面向对象分析与设计》课程报告

 1 任务一:阐述系统中用例的粒度大小应该如何控制。阐述对于同一个系统,不同用例粒度大小的区别以及其对系统的影响。系统的用例图,所包含的用例的数目应该如何确定。

 要求:

 (1)分析如何确定用例的粒度大小。给出几个典型的用例粒度选择不当的例子,解释用例粒度不当的原因,给出修改后的用例,并且比较修改前后的区别以及修改后的优势。

 。

 (2)以课程注册系统为背景,给出由于用例粒度不同得到的两个或者多个用例图,阐述由于不同的用例粒度大小对该系统的影响。

 (3)以自己做过的系统为背景,给出由于用例粒度不同得到的两个或者多个用例图,阐述同一个系统由于不同用例粒度大小对该系统的影响。

 ( (1)

 )

 分析如何确定用例的粒度大小。

 给出 几个典型的用例粒度选择不当的例子,解释用例粒度不当的 原因,给出修改 后的用例 ,并且比较修改 前后的区别 以及修改后的优势。

 。

 控制方法 1:(一种理解)严格来讲用例不存在所谓的粒度问题,出现这种问题更多的原因是因为误用了用例的概念。这种问题最主要的表现是系统分析师由于担心会遗漏掉系统中的各个功能细节,而在定义用例时过分细化,从而陷入了功能分解;用例也就不是用例了,而变成了各个功能单元,违背了用例提出的初衷,也不是面向对象的方法所提倡的抽象和封装思想。所以严格把握评价用例的标准来定义用例时避免用例粒度错误的关键,这条原则就是“用例是参与者所要实现的最终目标,并为参与者产生所需要的价值 ” 控制方法 2:(另一种理解)用例粒度的划分是根据该用例是否完成了参与者的某个完整的目的。一个大的用例适合还是分解成多个小用例合适这个没有一个标准的规则,但可以根据以下经验来做,在不同的阶段使用的粒度不同:在业务建模阶段,用例的粒度以每个用例能够说明一件完整的事情为宜。即一个用例可以描述一项完整的业务流程。这将有助于需求范围。例如取钱、报装电话、借书等表达完整业务的用例,而不要细节到验证密码、填写申请单、查找数目等业务中的一个步骤。

 在用例分析阶段,即概念建模阶段,用例的粒度以每个用例能描述一个完整事件流为宜。可以理解为一个用例描述一项完整业务中的一个步骤。需要注意的是,这个阶段需要采用一些面向对象的方法,归纳和抽象出业务用例中的关键概念模型并为之建模。例如,宽带业务需求中有申请报装和申请迁移地址用例,在用例分析时,可归纳和分解为提供申请资料、受理业务、现场安装等多个业务流程中都会使用的概念用例。

 在系统建模阶段,用例视角是针对计算机的,因此用例的粒度以一个用例能够描述操作者与计算机的一次完成交互为宜。例如,填写申请单、审核申请单、派发任务单等。可以理解为一个操作界面或一个页面流。另一个参考的粒度是一个用例的开发工作量在一周左右为宜。

 一般一个好的系统,用例在大于 10 个小于 50 个之间,否则应该考虑一下粒度的选择是否合适了。不管粒度如何选择,必须把握的原则是在同一个需求阶段,所有用例的粒度应该是同一个量级的。

 当然对于用例粒度问题有另外一种非常典型的情况,“CRUD 问题”(因像马车的四个轱辘, 所以又称为四轮马车问题,其中 C-creaet,R-read,U-update,D-delete,即数据库表的四种基本操作),如下图所示。

 《面向对象分析与设计》课程报告

 2

 从上图可以看出,对于商品管理员来说,对商品的操作明显是常规的增删改查这四种操作,但实际上这样的用例表述是有问题的,管理员所需的是可以对商品进行日常的维护管理,而增删改查的方法只是用来实现管理员进行管理商品的操作,所以从用例角度来分析,CRUD可以表示为“管理 XX”用例,如图下图所示

 应在用例的定义中尽量避免 CRUD 问题,不应该过分的注重数据库设计而忽视了需求定义与对象设计,更多因该从参与者的目标者入手。

 当然在实际的项目中应该灵活处理问题。如上述的 CRUD 问题,若管理用例含有多个独立分支的情况,在一定情况下也可以考虑把其中一些复杂的或有一定复用粒度的分支独立作为一个子用例而存在,并利用用例之间的关系使用例的结构更加合理,如上图,管理商品的用例中,考虑到“查询商品”也为普通用户的需求,所以有一定的复用性,因此可以将上图根据实际进一步改进为下图更加合理

 ( (2 )以 课程注册系统 为背景, 给出由于用例粒度不同得到的两个 或者多个 用例图, 阐述 由于 不同 的 用例粒度大小对 该 系统的影响。

 举例:过分的细化有不同的情形 1.如图

 《面向对象分析与设计》课程报告

 3

 这里把为完成一个用例而需要执行步骤当坐单个用例。另一种情况是把系统内部的一些处理过程分解为多个用例,这种错误往往在提取用例关系时出现,如下图:

 在这里设计者将“查询商品”用例分解为“建立数据库”和“执行 sql 语句”两个子用例。而事实上,这两个用例不时外部参与者所追求的目标,而是系统内部在设计实现时的一种方案,这样画出来的用例便不是需求,而是设计,不应该出现在用例图中

 举例 2.如一个读者去图书馆借书。首先他登录系统,查询书目,出事借书证,图书管理员查询该人以前借阅记录以确保没有未归还的书,最后该人借到了该书。如果从比较细的角度划分,以上每个过程都可以当做一个用例。

 但是用例分析是以参与者为中心的,因此用例的细化以能完成参与者目的为依据。这样,实际上适合用例是:借书。只有一个,其他都只是完成这个目的的过程。这个例子是比较明显的能够区分出参与者完整目的的。若是第一种场景,下图用例便是用例过细,没有很好的表达了用户的需求。

 《面向对象分析与设计》课程报告

 4 应该以用户的需求——借书为目的来描述用例,更改后如下图

 举例 3:

 再如在 ATM 取钱的场景中插卡、登录、取钱以及打印,退卡等都是可能的用例,显然,取钱包含了后续的其他用例,取钱粒度更大一些,其他用例的 粒度则要小一些。用户可以根据实际完成的目标来界定该设定用例。比如用户仅仅是完成取钱的任务,则可以将登录、取钱、打印回执作为用例,。

 而用户如果是要去旅行(旅行是目的),旅行要预定景点,游览景点,准备交通工具等等,取钱只是旅行中的一个需求部分,那么此时适合将取钱作为其中的一个用例,如下图

 《面向对象分析与设计》课程报告

 5

 ( (3 )以自己做过的系统为背景,给出由于用例粒度不同得到的两个或者多个用例图,阐述同一个系统由于不同用例粒度大小对该系统的影响。

 在这个学期我完成了图书网上销售哦管理网站,功能介绍大致如下 1. 管理员可以增删改查图书,也可以增删改查用户的账号。

 2. 用户可以购买图书,也可以浏览图书的详细信息。

 3. 用户可以将喜欢的图书添加到自己的购物车,当然也可以修改购物车中商品的数量,也可从购物车删除自己不喜欢的商品。

 4. 用户可以从购物车下单,可以查看自己的历史订单,也可以删除自己的历史订单。

 5. 若用户没有注册则不可以添加购物车与订购图书。在点击时自动跳入注册页面。

 在画用例图的时候应该时刻把握用例粒度应在同一粒度,而在写用例粒度时应注意尽量不出现计算机的专业术语,用例所描述是用来表达用户的需求。

 举例 1(违反控制方法 1):当分析管理员的需求时我发现管理员的操作可以增删改图书,查询图书信息,管理员课以增删改用户的账号,可以查询用户的信息,所以我便将自己所分析的管理员的每一个操作操作都作为一个用例,如下图(用例粒度过小):

 《面向对象分析与设计》课程报告

 6

 这样的用例分析图便是用例过细,在看这个用例图时我们便会发现,用例图过于繁杂,逻辑不清,从图中不能很明显的看出参与者所要实现的究竟是什么目标。而是着重描述了系统中的各个功能细节,所以倒置在定义用例时过分细化,从而陷入了功能分解;管理员的用例也就不是用例了,而变成了管理员的各个功能,违背了用例提出的初衷。

 所以为了将管理员用例表达合适,使用合适的粒度大小,就要根据用例所要描绘的用户的需求了确定分析合适的用例粒度。首先应该确定管理员的真正的需求其实是对图书的日常维护管理与对账户的日常维护管理,由于用户也有管理员的部分功能,所以将共有的功能提取,用 extend 的合适地表达,所在在分析了自己地错误与用例过细带来的影响,我将用例图重新绘制如下图:

 在这样改进后便会发现,用例图变得“清爽”,用例图明确的表达了管理员的需求就是对商品的维护与对账户的维护,并且也合适的表达了用户的需求,用例粒度较为合适,而不是如上图一样的表达过于偏向功能且粒度过小。

 举例 2(违反控制方法 2):在分析用例粒度时要根据用例所处于的阶段,合理的确定用例粒度的大小,然后判断用例是否完成了参与者的某个完整的目的,所以当分析用户购买图书的

 《面向对象分析与设计》课程报告

 7 用例图的时候,下图明显用例粒度过于大。

 在观察此用例图时,根据我们所要描述的用例需求与现在所处的阶段,由于在此阶段是要描述用户“购买图书”的需求用例,而不是,用例使用网上商城的用例,所以便可以很明显的发现上图用例过大,用例图完全没有描述参与者如何完成“购买图书”的目的的整个流程,所以将粒度减小再次分析用户“购买图书”的需求,购买图书需要完成以下事件,浏览商品,查询商品,添加到购物车,填写订单信息,支付费用。修改后的用例图如下。

 更改后的用例图,我们便可以清楚了解用户“购买图书”的需求是如何完成的。

 当然那么将“购买图书”作为单独的用例被描述,此时的用例粒度适用于什么情况,或者说什么阶段将适用这样的用例粒度大小,我们会发现当我们分析用户网上图书销售管理的用例时,此时将“购买图书”作为单独的用例便相对来说较为合适,如下图:

 《面向对象分析与设计》课程报告

 8 任务二:阐述用例间泛化、扩展关系的异同,对于选定的两个用例,如何确定用例间关系。

 要求:

 (1)分别阐述上述关系,阐述何时需要使用泛化或者扩展关系,给出例子。

 (2)以自己做过的系统为背景,阐述用例间使用这两种关系的区别,并给出两个确定的用例之间,最合适的用例关系。

 ( (1)

 )

 分别阐述上述关 系,阐述何时需要使用 泛化或者扩展 关系,给出例子。

 1.扩展关系 用一个用例(可选)扩展另一个用例(基本例)的功能,将一些常规的动作放在一个基本用例中,扩展关系是指某个用例(基用例,主用例)在特定情况下无法进行处理,而把这些行为委托给其他用例(扩展用例,子用例)

 扩展用例是为了将基用例的一些特殊情况分离出来,在保持基用例本身相对完整的情况下(一般情况都可处理)来处理这些特殊行为。另一种角度来说,扩展关系实在不改变基用例的情况下,对基用例的行为进行扩展,即将一些附加的行为添加到基用类中。这就意味着,扩展用例不会影响到基用例的内部行为(基用例不受扩展影响);而且基用例本身是完整的(不需扩展也可以向参与者提供价值)。

 举例 1:在图书管理系统中,当借书人要还书的时候有两种情况,一种情况是没有超出借书的期限,另一种情况便是超出了借书的期限,这两种情况是都有可能发生的,但不是必然会发生的,所以在这里便应用了扩展,如图所示。

 举例 2:系统中允许用户对查询的结果进行导出、打印。对于查询而言,无论可不可以导出、打印,对于查询都是一样的(即它们对查询没有影响),导出、打印是不可见的。导入、打印和查询相对独立,而且为查询添加了新行为。因此可以采用扩展关系来描述:

 《面向对象分析与设计》课程报告

 9 2.泛化关系 子用例继承了父用例所有的结构、行为和关系,是父用例的一种特殊形式。用例之间的泛化表明了一种继承层次,通过这种继承层次,特化的用例继承泛化用例的全部属性与行为,并且参与泛化用例的各种关系。通过用例之间的返还关系可以达到更高层次的复用需求,在泛化用例中描述通用行为,而贴画用例继承这些通用行为,在适当的地方进行特化,以处理具体的业务。泛化往往作为抽象用例而存在,即泛化的用例不会产生任何具体的场景实例,是为了需求复用而提出,具体的场景实例都应该来自特化的用例;或者说参与者实际上是通过执行特化的用例来实现目标的。

 举例 1:设想这样一个场景普通售货员可以取消小交易,而高级售货员可以取消大交易,小交易与大交易都有交易的共同属性,按照如此描述,运用泛化设计用例图如下

 举例 2:,我们知道工作中中可能存在许多需要部门领导审批的事情,虽然审批的内容不同,审批的对象不同,但是领导审批的流程是很相似的,这时可以根据审批的过程分析出共有的需求,再根据不同的对象与内容做成泛化关系表示,如图所示:

 2.扩展关系的异同:

 泛化表示类似于 “继承”或“多态”。UML 中的用例泛化过程是将不同用例之间的可合并部分抽象成独立的父用例,并将不可合并部分单独成各自的子用例;包含以及扩展过程与泛化过程类似,但二者对用例关系的优化侧重点是不同的。如下:

  1、泛化侧重表示子用例间的互斥性;

  2、扩展侧重表示扩展用例的触发不定性;详述如下:

  既然用例是系统提供服务的 UML 表述,那么服务这个过程在所有用例场景中是必然发生的,但按照发生条件可分为如下两种情况:

 《面向对象分析与设计》课程报告

 10

  ⒈无条件发生:肯定发生的;

  ⒉有条件发生:未必发生,发生与否取决于系统状态;

  因此,针对用例的两种关系结合系统状态考虑,泛化用例属于无条件发生的用例,而扩展属于有条件发生的用例。进一步,用例的存在是为参与者提供服务,但用例提供服务的方式可分为间接和直接两种,依据于此,泛化中的子用例提供的是直接服务,而包含中的被包含用例提供的是间接服务。同样,扩展用例提供的也是直接服务,但扩展用例的发生是有条件的。

 泛化关系代表的一种一般和特殊的关系,而扩展关系也有这样一层含义(即用例表达到某种特殊情况);因此,有些情况下的泛化关系可以转化成扩展关系,如下图

 第一个图采用泛化关系用户可以通过密码和指纹两种手段的登陆,参与者通过其中之一登陆。而第二幅图采用扩展关系,其中登陆用例是具体用例,代表用户通过密码登陆(作为基用例)。但用例存在扩展点,用户可以在扩展电商选择另外一种登陆手段。

 另外一点需要提及的是:泛化中的子用例和扩展中的扩展用例均可以作为基本用例事件的备选择流而存在。

 ( (2)

 )

 以自己做过的系统为背景, 阐述用例间使用这两种关系的区别,并给出两个确定的用例之间,最合适的用例关系。

 在这学期的 Oracle 数据库的大作业中,我完成了学生信息管理系统,学生信息管理系统部分功能性需求包括以下内容:

 (1)

 系统管理员登录后可以对班级的基本信息进行增加、删除、修改、查询等操作。

 学校领导登录后可以对班级基本信息进行查询操作。

 (2)教师登录后可以对学生的考试成绩进行录入、删除、修改、查询等操作。学生登录后可以对考试成绩进行查询操作。

 (3)学生登录后可以了解所有选修课程的具体信息,可以根据自己的需要选择不同课程。系统管理员登录后可以增加、修改、查询、删除选修课程。

 (4)系统管理员可以对账号进行创建、设置、查看、删除等操作,可以发布消息。

 扩展关系举例:

 1.系统管理员,老师,学生直接参与的用例包括登录,登录过程中发生忘记密码的情况,就需要使用找回密码的功能来找回密码,而在正常情况下用不到找回密码这个功能所以用例“找回密码”和用例“登录“之间是扩展关系。

 2.管理员直接参与的用例除了登录、找回密码还有查看班级基本信息、删除班级基本信息、修改班级基本信息和录入班级基本信息。而且校领导也直接参与用例登录、找回密码和查看

 《面向对象分析与设计》课程报告

 11 班级基本信息。对于管理班级信息中查询班级信息,不是必然会发生的,而对于校长查询班级信息是必然发生的,这样讲查询班级从管理班级信息抽出作为管理班级信息的一个用例,最合适便是用扩展来表达。

  泛化关系:举例 1.学生在选择课程的时候有连个选择,一个是选择主修课,一个是选择选修课,两者有着共同的“选课的过程”,选择选修课于选择主修课继承选课的全部内容,所以最适用于泛化用例:

 泛化与扩展的综合应用:举例 1.在学生管理系统中,老师可以添加学生成绩,也可以修改学生成绩,成绩分为平时成绩与考试成绩,在添加成绩时,平时成绩与考试成绩都为必填项,而在修改成绩的时候,平时成绩与考试成绩必须选择一个或两个进行更改,由于这样的的关系,修改平时成绩与修改考试成绩的两个用例在添加成绩的流程是是很相似的,这时可以用泛化关系表示。在修改成绩之前教师可能会对成绩进行查询所以将“查询成绩”作为“修改成绩”的扩展,这时可以可以用扩展关系来表示

 《面向对象分析与设计》课程报告

 12

  任务三:类之间可以有泛化、关联、聚集、依赖关系,请给出这些关系的比较。

 要求:

 (1)分别阐述上述关系,阐述何时需要使用上述关系,分别给出例子。

 (2)以自己做过的系统为背景,阐述类之间使用这些关系的区别,并给出两个确定的类之间,最适合的关系。

 (3)以自己做过的系统为背景,阐述这些原则的应用以及优势。重点阐述项目中,如何应用这些原则,并且比较使用这些原则和未使用之间的区别,进而进一步阐述这些原则的优势。

 ( (1)

 )

 分别阐 述上述关系,阐述何时需要使用 上述 关系, 分别 给出例子。

  1. 泛化(Generalization)

 泛化关系:是一种继承关系,表示一般与特殊的关系,它指定了子类如何特化父类的所有特征和行为,及由父类具体化一个子类。

 箭头指向:带三角箭头的实线,箭头指向父类 例如:一个 Studen 类,一个警察 Policemen 类,两个类均继承自 Person 类,那么他们的类关系图表示如下:

 《面向对象分析与设计》课程报告

 13

 2:关联关系是一种比较强的关系,他们的关系是比较持久的,稳定的。关联分单向关联和双向关联还有自关联,如果一个类知道或者引用了另一个类,而另一个类不知道或者没有引用这个类,则这两个类是单向关联的。双向关联是两个类彼此都知道对方的存在。可能会存在一些类的属性对象类型为该类本身,这种特殊的关联关系称为自关联。

 举例 1(单项关联):学生与家的关系就是单向关联的,因为每个学生都是有个家的(不考虑孤儿),但不能说每个家里都有学生。单向关联我们用带箭头的实线表示,箭头指向被引用或者被包含的类,这里也就是家这个类。示例如下:

 举例 2(双向关联):双向关联是两个类彼此都知道对方的存在,比如老师与学生的关系就是双向的。小王的语文老师是张老师,张老师的学生有小王。双向关联用不带箭头的实线来连接两个类。示例如下:

 《面向对象分析与设计》课程报告

 14 举例 3(自关联):类的属性对象类型为该类本身如一个节点类(Node)的成员又是节点 Node类型的对象,本质上来说也应为单项关联,示例如下:

  3:聚集:也称为聚合, 是一种特殊的关联关系,聚合关系强调的是整体和部分的关系,其中部分可以脱离整体而存在。

 UML 类图中聚合用带空心菱形的直线表示,其中菱形指向整体:

 举例 1 电脑与鼠标的关系,鼠标是电脑的一部分,鼠标可以脱离电脑而存在。

  4:依赖关系:依赖关系是一种很弱的关系,是一种使用的关系,即一个类的实现需要另一个类的协助,所以要尽量不使用双向的互相依赖. 举例 1:学生捡到钱给警察是一种偶然的事情,学生和警察叔叔就是一种依赖关系,交给警察后他们之间就没有关系了,示例如下。

  ( (2)

 )

 以自己做过的系统为背景,阐述类之间使用这 些 关系的区别,并给出两个确定的类之间,最适 合 的关系。

 最近做了网上购书商城的 web 项目,在这里我以此项目背景来阐述关于类之间使用关系的区别与两个确定类之间最适合的关系 1.用户分为游客与注册用户,游客只能浏览商品与查看详情,注册用户包括了游客的行

 《面向对象分析与设计》课程报告

 15 为而且还可以支付账单与添加购物车,他们之间最适合的关系为泛化

 2.每一个注册用户都有唯一的购物车相对应,他们之间最适合的关系是关联中的单向关联,图如下

 3.商品与购物车,多个商品的购买组成了购物车,而没有购物车商品页可以单独存在,所以商品与购物车最适合的关系为聚合,图如下

  4.用户只有点击添加商品的时候,商品才会被添加到购物车,若不点击,用户与商品是没有联系的,所以用户与商品最合适的便是依赖的关系

 《面向对象分析与设计》课程报告

 16

  任务四:开闭原则、Liskov 替换原则、依赖倒置原则的比较。

 要求:

 (1)请分别详细阐述这些原则的基本内容,并分别给出这些原则的实现方式以及使用这些原则的例子。

 (2)以课程注册系统为背景,阐述这些原则的应用以及优势。重点阐述项目中,如何应用这些原则,并且比较使用这些原则和未使用之间的区别,进而进一步阐述这些原则的优势。

 ( (1)

 )

 请 分别详细阐述这 些 原则的基本内容,并分别给出这些原则的实现方式以及使用这些原则的例子。

 开闭原则:对扩展开发,对修改关闭。更加直观的描述便是:不能修改已有的软件模块(即修改封闭),从而不影响依赖于该模块的其他模块;通过在已有模块的扩展新模块来扩展模块功能(即扩展开放),从而应对需求变更或新需求。由于不可能完全预知软件实体的所有元素,因此需要保持一种灵活性一遍尽可能地应对未来的变更和扩展。

 原则的实现:核心思想是对抽象编程,而不对具体编程,让类依赖于固定的抽象,这样对修改就是封闭。而通过面向对象的继承和多态机制,就可以实现对抽象体的继承,通过覆写其方法来改变固有行为。将经常发生变化的状态和行为封装成一个抽象类(或接口),外部模块将依赖于这个相对固定的抽象体,从而实现对修改的封闭。同时,针对不同的变化可以扩展不同的派生类,从而实现对扩展的开放。

 举例 1:这样一个场景,我们有各式各样的衣服,先抽取两个实体类“人”和“上衣” 人穿上衣,建立“人”到“上衣”的关系联系

 虽然可以很好的满足“人穿上衣“的需求,但这不是一个满足开闭原则的设计方案,因为两个具体”peopel“和”jacket“之间紧密耦合,从而无法应对需求的变更或新的需求。考虑新的需求:人穿裤子,鞋子,裙子,手套..等其他物品,此时不可避免的要修改现有程

 《面向对象分析与设计》课程报告

 17 序,如图添加了”人穿裤子“需求后的设计方案

 我们会发现由于对 people 做了修改,“手穿上衣“也受到了影响,途中若该对象同时拥有 jacket 与 pants 对象的引用,do()的职责原型也将被修改,需要添加新的参数,显然上图的设计方案有了僵硬性与脆弱性。这时使用开闭原则重新设计,考虑会”穿“各式各样的衣服,而衣服也有各自的能力反应人的能力,所以把这种能力作为接口,能响应该能力的对象负责实现这些接口。这样就用开闭原则实现的新的方案:如下图:

 这样便保证了程序的可扩展性,也满足开闭原则

 2 里氏替换原则:子类型必须能够替换他们的基类型,即对于继承层次的设计,要求在任何情况下,子类型与基类型都是可以互换的,那么该继承层次的设计就是合适的,否则就可能出现问题 实现方法:1.尽量把父类设计为抽象类或者接口,让子类继承父类或实现父接口,并实现在父类中声明的方法,运行时,子类实例替换父类实例,我们可以很方便地扩展系统的功

 《面向对象分析与设计》课程报告

 18 能,同时无须修改原有子类的代码,增加新的功能可以通过增加一个新的子类来实现。里氏替换原则是开闭原则的具体实现手段之一。2.也可以将违反里氏替换原则的行为移除基类型。

 举例 1:鸟一般都会飞行,燕子会飞 但是鸡属于鸟类但鸡却不会飞假如要设计一个实例,如果计算这两种鸟飞行 300 千米要花费的时间。显然,拿燕子结果正确,能计算出所需要的时间;但拿鸡来测试,结果会发生 “无穷大”,明显不符合预期,其类图如图 1 所示。

 这时候利用里氏替换原则:定义一个更加广泛的类,如动物类,将动物行为设为跑,这样就包括了鸡不能飞如下图。

 3 依赖倒置原则:高层模块不应该依赖于底层模块,两者都应该依赖于抽象。抽象 不应该依赖于细节,细节应依赖于抽象。

 具体实现:多使用接口与抽象类,而少使用具体的实现类。利用这些抽象将高层模块(如

 《面向对象分析与设计》课程报告

 19 类的调用者)与具体的被操作者(如具体类)隔离开,从而使具体类在发生变化时不至于对调用者产生影响,简单而言让高层与底层都去依赖接口。更好的方法是由高层模块来定义而底层则取实现这些服务。这样当底层实现逻辑发生改变时,高层模块将不受影响。

 举例 1:设想司机开车的场景,设计驾驶员驾驶奔驰汽车的时候,因为场景单一,很有可能就会陷入到面向实现编程

 显然这不满足 DIP 的方案,driver 直接依赖具体类 bens,它直接 new 出 bens 的对象,并调用方法。假设司机想开宝马,宝马对象有了,却不能让司机开起来。我们的设计出了问题:司机类和奔驰类之间是紧耦合的关系,其导致的结果就是系统的可维护性大降低,可读性降低。所以根据 DIP 原则,需要为 bens 类建立抽象接口,从而消除这种直接依赖,示例如下

  ( (2)

 )

 以课程注册系统为背景,阐述这些原则的应用以及优势。重点阐述项目中,如何应用这些原则,并且比较使用这些原则和未使用之间的区别,进而进一步阐述这些原则的优势。

 1 里氏替换原则 在课程注册系统中,老师的角色有多种,如教授,副教授,讲师,因为会发现教授,副教授,讲师都会有一些共同的不变的功能如查看课程信息,查看选择课程的学生,设置学生成绩。

 若未使用的话:设想一个场景,老师,同学可以查看个人信息,同学可以查看课程,选课,与查看自己信息,老师可以查看课程信息,添成绩。

 《面向对象分析与设计》课程报告

 20

 使用和未使用之间的区别:虽然老师学生都可以使用这些功能,但我们会发现,学生不能设置成绩,老师不能选课啊,但给出的例子却可以,老师学生的不应该有的功能在父类中存在,问题的所在便是没有使用里氏替换原则导致子类功能没有覆盖父类功能,现在我们引入里氏替换原则:

 得出的优势:减少了代码冗余,提高了程序的扩展性,我们可以很方便地扩展系统的功能,同时无须修改原有子类的代码,增加新的功能可以通过增加一个新的子类来实现 2.依赖倒置原则:

 在课程注册系统中,学生会评价不同的老师,虽然大部分老师会有相同的评教规则,但不同专业不同方向的老师可能会有不同的评教体系,随着每学期的变化,老师的评教规则可能会变更。

 若未使用:设想一个场景:假设现在,只有体育老师,学生评价体育老师。

 《面向对象分析与设计》课程报告

 21

  使用和未使用之间的区别:虽然学生可以评价体育老师。但若有新的老师,如数学老师,该怎么办?当然可以新建一个数学老师类,在添加一个 Order()方法,但问题是,虽然数学老师类建好,但学生此时没有方法评价,上面的设计没有使用依赖倒置原则,所以我们发现模块与模块之间耦合度太高,生产力太低,只要需求一变就需要大面积重构,说明这样的设计是不合理。现在我们引入依赖倒置原则,重新设计的类图如下:

 得出优势:依赖倒置原则的优点:提高扩展性,代码层次更加清晰,降低耦合度,将高层模块与具体的操作者隔离开,使得具体类发生变化而没有对调用这产生影响,提高了系统的稳定性,减少并行开发引起的风险,而且提高代码的可读性和可维护性。

 3.开放封闭原则 在课程注册系统中,管理员会对课程信息会不断的进行维护,如增加删除课程,发布课程,更改课程,而对于课程新的维护以后可能还会添加更多的功能,为了在以后修改或添加功能的时候不会对原有的系统做出改变所以在这里运用开放封闭原则

 若未使用:设想一个场景,管理员要不断对课程信息进行维护,假设现在管理员有一个删除课程的维护的方法,

 《面向对象分析与设计》课程报告

 22

  使用与未使用的区别:由于管理员对维护课程的操作有很多,如发布课程,修改课程,随着时间,功能可能会不对增多,若不适用开放封闭原则,每增加一个功能必然会对administers 进行更改,程序灵活性非常低,僵硬脆弱,所以对类图进行更改,应用开放封闭原则,重新设计的类图如下

 得出的优势: :用抽象构建框架,用实现扩展细节。因为抽象灵活性好,适应性广,只要抽象的合理,可以基本保持软件架构的稳定。而软件中易变的细节,我们用从抽象派生的实现类来进行扩展,当软件需要发生变化时,我们只需要根据需求重新派生一个实现类来扩展就可以,增强了程序的灵活性,可用性,以及可维护性

 ( (3 )以自己做过的系统为背景,阐述这些原则的应用以及优势。重点阐述项目中,如何应用这些原则,并且比较使用这些原则和未使用之间的区别,进而进一步阐述这些原则的优势。

  在上个学期的 java 面向对象的课程中,我们小组大作业做的是类似于“植物大战僵尸”的一类小游戏,在这里我以此项目背景来阐述关于这些原则的应用以及优势,以及使用与未使用之间的区别,进而进一步得出这些原则的优势 在这个游戏中植物是用来防御僵尸的,植物有很多种:如豌豆射手,坚果,太阳花,等等。每个植物的作用与动作都不相同,但他们都属于植物,从中抽象出他们共有的属性,再将每个植物特有的作用与动作在子类中实现,这里便运用了里氏替换原则 若未使用:植物有很多种,假设这样一个场景,坚果与豌豆射手继承自父类植物类

 《面向对象分析与设计》课程报告

 23

  使用原则与未使用原则的区别:坚果和豌豆都继承自植物类,但这是就会出现了一个问题,坚果没有攻击这个方法啊,所以就出现了坚果不能覆盖父类植物类的所有属性与方法,说明这样的设计是不合理。现在我们引入里氏替换原则,重新设计的类图如下:

  由里氏替换原则:plant 抽象出了每个植物都共有的属性:血量与名字,和他们共有的行为:设置血量。在它的子类中实现每个植物特有的行为 里氏替换原则的优势:代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性; 提高代码的重用性;子类可以形似父类,但又异于父类;使各个类之间的逻辑更加清晰明确 而不至于混乱 2 依赖倒置原则:在这个小游戏中,植物会对僵尸进行攻击,由于不同的僵尸对同一个植物所收到的攻击而减少的血量与动作的反应是不同的,所以将他们收到攻击后减少的血量与反应的动作抽象出来成为接口,这里便使用了依赖倒置原则 若未使用原则:假设这样一个场景豌豆可以攻击普通僵尸,设计类图如下

 《面向对象分析与设计》课程报告

 24

 使用与未使用的区别:当然:如果只有一个普通僵尸,这样设计是没有问题的,可是在游戏实际中,僵尸有很多种类,如跳跃僵尸,高级僵尸,随着游戏进程,会有越来越多的僵尸,若要使植物可以攻击其他种类的僵尸,若不使用依赖倒置原则,每增加一个僵尸必然会对plant 进行更改,植物类和低等僵尸类之间是紧耦合的关系,其导致的结果就是系统的可维护性大降低,可读性降低,而小组成员在考虑僵尸收到伤害的时候还要考虑植物的攻击,效率降低,可读性也大大降低。所以对类图进行更改,应用开放封闭原则,重新设计的类图如下

  使用的优点:将类的调用者(植物)与具体的被操作者(不同的僵尸)隔离开,从而使僵尸类在发生变化时不至于对调用者(植物)产生影响,可以通过抽象使植物与僵尸彼此独立,不互相影响,而且我们小组内可以分工僵尸一起写不同的僵尸类,不用考虑对植物的影响 。

 依赖倒置的优势:采用依赖倒置原则可以减少类间的耦合性,将高层模块与具体的操作者隔离开,使得具体类发生变化而没有对调用这产生影响,提高了系统的稳定性,减少并行开发引起的风险,而且提高代码的可读性和可维护性。

 开放封闭原则:植物大战僵尸小游戏中,大部分僵尸只有走进植物才可以吃掉植物,但也有一些特别的僵尸,他们有的可以越过前面的植物吃后面的,有的植物还可以远程攻击植物,有的僵尸还可以召唤出新的僵尸,因为想到以后还可能开发更多的有特殊功能的僵尸,但不能改变原有的僵尸,所以这里便要运用到了开放封闭的原则

 《面向对象分析与设计》课程报告

 25 若不使用原则:假设这样一个场景,普通僵尸遇到植物会吃植物,即植物收到伤害,这时若不使用原则这样设计,如图

 使用与未使用的区别:如果只有这两个种类的僵尸这样设计可以使用,可是在游戏实际中,不同的僵尸吃的方式不同,吃的方向不同,如跳跃僵尸会吃下一个植物,高级僵尸也会吃旁边的植物,随着游戏进程,会有越来越多不同的僵尸,若不使用开放封闭原则,每增加一个僵尸必然会对 plant 进行更改,植物类和低等僵尸类之间是紧耦合的关系,由于有些僵尸有自己特别的功能,若要添加功能就要在原有存在的类中进行修改,从而无法应对僵尸技能的变更,或者新的需求,这时就要不可避免的修改现有的程序,说明这样的设计是不合理。现在我们引入开放封闭原则,重新设计的类图如下:

 使用:提供一个“特别攻击的接口”让有特殊功能的僵尸继承这个接口,而不可以去修改原有的僵尸类,每新添一个有特殊功能的僵尸就继承这个接口,这样就实现了对原有类修改封闭,对新增功能开放 开放封闭原则的优点:保证了程序的可扩展性,对一些不必要的复杂性进行了避免,通过已有的模块的扩展新模块来扩展功能,这样灵活应对了需求的变更 任务五:给出顺序图、状态图、活动图的比较。

 要求:

 (1)请阐述这些图的区别。

 《面向对象分析与设计》课程报告

 26 (2)分别给出,这些图最适合描述哪些情况,并给出例子。

 (3)以自己做过的系统为背景,分别阐述何时需要使用这些图,并给出例子。

 以机房管理系统为例

 ( (1 )请阐述这些图的区别。

 活动图(activity diagram,动态图)

 活动图描述满足用例要求所要进行的活动以及活动间的约束关系,有利于识别并行活动。活动图是一种特殊的状态图,它对于系统的功能建模特别重要,强调对象间的控制流程。

 它阐明了业务用例实现的工作流程。业务用例工作流程说明了业务为向所服务的业务主角提供其所需的价值而必须完成的工作。业务用例由一系列活动组成,它们共同为业务主角生成某些工件。工作流程通常包括一个基本工作流程和一个或多个备选工作流程。工作流程的结构使用活动图来进行说明。活动图是状态图的一种特殊形式。其中所有或多数状态都是活动状态,而且所有或多数转移都在源状态中的活动完成时立即触发。

 状态图(Statechart Diagram)是描述一个实体基于事件反应的动态行为,显示了该实体如何根据当前所处的状态对不同的事件做出反应的。通常我们创建一个 UML 状态图是为了以下的研究目的:研究类、角色、子系统、或组件的复杂行为。状态图用于显示状态机(它指定对象所在的状态序列)、使对象达到这些状态的事件和条件、以及达到这些状态时所发生的操作。

 顺序图显示对象之间的动态合作关系,它强调对象之间消息发送的顺序,同时显示对象之间的交互。将交互关系表示为一个二维图。纵向是时间轴,时间沿竖线向下延伸。横向轴代表了在协作中各独立对象的类元角色。类元角色用生命线表示。当对象存在时,角色用一条虚线表示,当对象的过程处于激活状态时,生命线是一个双道线。顺序图是一种动态建模方法。

 顺序图、状态图、活动图的区别与联系:UML 顺序图一般用于确认和丰富一个使用情境的逻辑交互图强调的是对象到对象的控制流,而活动图则强调的是从活动到活动的控制流,活动图是一种表述过程基理、业务过程以及工作流的技术。活动图与状态图都是状态机的表现形式,但是两者还是有本质区别:状态图着重描述从一个状态到另一个状态的流程,主要有外部事件的参与。它可以用来对业务过程、工作流建模,也可以对用例实现甚至是程序实现来建模 ( (2)

 )

 分别给出,这些图最适合描述哪些情况,并给出例子。

 活动图:用例文档描述了用例的业务流程,有些用例的流程比较复杂(如存在分支,循环等复杂结构),而这个流程只用文本描述的话并不直观,不利于用户之间的沟通。因此可以采用活动图来描述该用例内部的执行流程,主要用于描述某一种方法,机制或用例的内部行为。活动图使用的场合有业务建模,需求,类设计。

 举例 1:对于图书管理系统用例模型,尤其是复杂的用例,均可以采用活动图来表示, 如下图借书用例的活动图:

 《面向对象分析与设计》课程报告

 27

  2:顺序图是用于显示对象间的交互活动,它关注对象之间传送的时间顺序。合适的使用场合为用例分析,用例设计

 3.状态图:有时对象本身也是很复杂的,他可能设计不同的状态和行为,此时需要通过

 《面向对象分析与设计》课程报告

 28 状态图来表示,利用状态和时间描述对象本身的行为。强调事件倒置的对象状态的变化,适用场合类设计 举例:图书管系统中,图书涉及不同的状态,新买来的图书是“待入库状态”。工作人员完成新书入库后,图书转为“待借状态”,图书借出后转为“借出状态”,归还后又转为“待借状态”,不断循环。不同的状态会有不同的行为,如“借出状态”的图书就不再允许出界,如图所示

 ( (3)

 )

 以自己做过的系统为背景,分别阐述何时需要使用这些图,并给出例子。

 以机房管理 系统为例 1. 用户若想使用机器,先选出机器的位置,在向管理员出示相关的信息 2. 若用户卡内有余额可以使用机器,若余额为零则机器出于待机状态 3. 管理员负责将用户信息输入,并且查看机器状态,与控制机器的状态 顺序图 1.管理员登陆进入管理页面,并管理用户与相关的机器信息。顺序图虽然不能很好的显示复杂过程的逻辑,但顺序图可以很好的显示对象沿生命线发展,对象之间随时间的交互,若想表达各对象之间的发生顺序与随时间的交互使用顺序图便可以很好的描述,如下图描述了管理员与用户机器之间随着时间的交互顺序。

 《面向对象分析与设计》课程报告

 29 顺序图 2:临时用户使用机器的流程,临时用户出示信息,操作人员核实,核实通过后,操作员多退少补,然后更新工作记录、更新卡的状态。若目的适用于按照交互发生的一系列顺序,显示对象之间的这些交互的过程,此时顺序图便是很好的表达方式,如下图

 状态图:举例 1:在机房管理系统中机器涉及到不同的状态,没有被使用的机器处于“空闲状态”,当用户完成验证使用机器的时候,机器便处于“工作状态”,当用户余额不足的时候机器又会转为“待机状态”这些状态同时影响者机器的行为,若要描述机器的状态行为变化此时适用于状态图,如下图。

  活动图:用户开始使用机器与管理员的交互过程,有些用例的流程比较复杂(如存在分支,循环等情况),如果只用顺序图用来描述的话并不是非常直观,而且不利用用户之间的沟通, 活动图描述的是对象活动的顺序关系所遵循的规则,它着重表现的是系统的行为, 因此

 《面向对象分析与设计》课程报告

 30 若想要表达用户与管理员之间的顺序与行为可以用活动图来描述用户使用机器来描述用例内部的执行流程,

  综上个人所举的例子,以及根据所要表达的内容和所适用的情况选取合适的图,我们可以做出如下的总结

 1. 顺序图侧重描述事按照交互发生的一系列顺序,显示对象之间的这些交互的过程,可以用于确认和丰富一个使用情境的逻辑,着重体现对象间消息传递的时间顺序。顺序图允许直观的表示出对象的生存期,生存期内,对象可以对输入消息作出响应,并且可以发送消息。

 2. 活动图侧重描述事物本身的行为特征,以及描述对各对象跨越多个用例时的总貌 于对系统的动态行为建模的另一种常用工具,它描述活动的顺序,展现从一个活动到另一个活动的控制流。活动图在本质上是一种流程图。活动图着重表现从一个活动到另一个活动的控制流,是内部处理驱动的流程。

 3. 状态图主要用于描述一个对象在其生存期间的动态行为,表现为一个对象所经历的状态序列,引起状态转移的事件,以及因状态转移而伴随的动作,一般可以用对一个对象的生命周期建模,状态图用于显示状态机,重点在与描述状态图的控制流。

推荐访问:任务书 面向对象 课程
上一篇:20XX年会计工作总结,1
下一篇:综合模拟2020年公务员考试每日练习:图形推理-337-含答案

Copyright @ 2013 - 2018 优秀啊教育网 All Rights Reserved

优秀啊教育网 版权所有