可复用面向对象软件的基础
1.面向对象设计最困难的部分是将系统分解成对象集合。因为要考虑许多因素:封装、粒度、依赖关系、灵活性、性能、演化、复用等等,它们都影响着系统的分解,并且这些因素通常还是互相冲突的。
2.面向对象设计方法学支持许多设计方法。你可以写出一个问题描述,挑出名词和动词,进而创建相应的类和操作;或者,你可以关注于系统的协作和职责关系;或者,你可以对现实世界建模,再将分析时发现的对象转化至设计中。至于哪一种方法最好,并无定论。
3.设计的许多对象来源于现实世界的分析模型。但是,设计结果所得到的类通常在现实世界中并不存在,有些是像数组之类的低层类,而另一些则层次较高。例如, Composite(4.3)模式引入了统一对待现实世界中并不存在的对象的抽象方法。严格反映当前现实世界的模型并不能产生也能反映将来世界的系统。设计中的抽象对于产生灵活的设计是至关重要的。
4.设计模式帮你确定并不明显的抽象和描述这些抽象的对象。例如,描述过程或算法的对象现实中并不存在,但它们却是设计的关键部分。Strategy(5.9)模式描述了怎样实现可互换的算族。State(5.8)模式将实体的每一个状态描述为一个对象。这些对象在分析阶段,甚至在设计阶段的早期都并不存在,后来为使设计更灵活、复用性更好才将它们发掘出来。
- 委托

委托不用继承被委托的对象,委托类指向包含一个自己需要的方法,并把被委托的对象当做this指针传进来而不是传自己。
委托的主要优点在于它便于运行时刻组合对象操作以及改变这些操作的组合方式。假定矩形对象和圆对象有相同的类型,我们只需简单的用圆对象替换矩形象,则得到的窗口就是圆形的。
委托与那些通过对象组合以取得软件灵活性的技术一样,具有如下不足之处:动态的、高度参数化的软件比静态软件更难于理解。还有运行低效问题。
关联运行时刻和编译时刻的结构
- 聚合和相识
聚合:是编译阶段包含,意味着一个对象对另一个对象负责。一般我们称一个对象包含另一个对象或者是另一个对象的一部分。聚合意味着对象和其所有者具有相同的生命周期。
相识:是运行阶段赋值,意味着一个对象仅仅知道另一个对象。有时相识也称为“关联”或“引用”关系。相识的对象可能请求彼此的操作,但是不为对方负责。是一种比聚合要弱的关系,它只标识了对象间松散的耦合关系。(C语言的面向对象编程对象和函数只能是相识关系,即保存函数的指针,因为C语言不能在对象内定义方法)
聚合和相识在代码调用时完全一样,相识关系出现的频率较高,更具动态性,有时只存在某个操作期间,运行是可以不同时刻可以相识不同的对象,相识也使得它在源代码中更难被辨别出来。
设计应支持变化
1.获得最大限度复用的关键在于对新需求和已有需求发生变化时的预见性,要求你的系统
设计要能够相应地改进。
2.为了设计适应这种变化、且具有健壮性的系统,你必须考虑系统在它的生命周期内会发
生怎样的变化。一个不考虑系统变化的设计在将来就有可能需要重新设计。
- 导致重新设计的一般原因,及解决:
1)通过显示地指定一个类来创建对象。
在创建对象时指定类名将使你受特定实现的约束,而不是特定接口的约束,这会使未来的变化更复杂。要避免这种情况,应间接地创建对象(通过对象的相识使对象的实现更加灵活,而不是聚合将对象定义死)。
2)对特殊操作的依赖。
当你为请求一个特殊的操作时,完成该请求的方式就是固定下来了。为避免把请求代码写死,你将可以在编译时刻或运行时刻改变响应请求的方法。(通过传参调用函数,或者相识)
3)对硬件和软件平台的依赖。
外部的操作系统接口和应用编程接口(API)在不同的软硬件平台上是不同的。依赖于特定平台的软件将很难移植到其他平台上,甚至很难跟上本地平台的更新。所以(设计系统时限制其平台相关性就很重要了)。
4)对对象表示或实现的依赖。
知道对象怎么表示、保存、定位或实现的客户在对象发生变化时可能也需要变化。(对客户隐藏这些信息阻止连锁变化)
5)算法依赖。
算法在开发和复用时常常被扩展、优化、和替代。依赖于某个特定的算法的对象在算法发生改变时不得不变化。(因此有可能发生变化的算法应该被孤立起来)
6)紧耦合。
1.紧耦合的类很难独立地被复用,因为它们是互相依赖的。紧耦合产生单块的系统,要改变或删除一个类,你必须理解和改变其它的许多类。这样的系统是一个很难学习、移植和维护的密集体。
2.松散耦合提高一个类独立被复用的可能性,并且系统更易于学习、移植、修改和扩展。设计模式(使用抽象耦合和分层技术来提高系统的松散耦合)
7)通过生成子类来扩充功能。
每个新的子类都有固定的实现和开销(初始化、终止处理等)。定义子类还需对父类有深入的了解。一个通过定义子类继承父类的操作。会导致子类的方法爆炸,即时对一个简单的扩充,你也不得不引入许多新的不需要的子类方法、属性。(一般可通过委托的技术,是继承外对象行为的另一种灵活方法,新的功能可以通过以新的方式组合已有对象,而不是通过全部继承父类的方式添加到应用中去),另外过多使用对象组合会使设计难于理解,许多设计模式产生的设计中,(你可以定义一个子类,且将它的实现和已存在的实例进行组合来引入定制的功能)
8)不能方便地对类进行修改。
有时你不得不改变一个难以修改的类属性。或者可能对类的任何改变都要求必须修改许多已存在的其他的子类。(设计类时应提供这些情况对类属性的修改的方法)
应用程序
应用程序内部的复用性、可维护性和可扩充性要优先考虑。
内部复用性:确保你不会做多余的设计和实现,设计时通过减少依赖性来提高内部复用性。
1.松散耦合也可增加一类对象与其他多个对象协作的可能性,例如,通过孤立和封装每一个操作,以消除对特定操作的依赖。消除对算法和表示的依赖。
2.系统设计分层和限制对平台的依赖性,它们将会使一个应用更具有可维护性。
3.通过显示怎样扩展类层次结构和怎样使用对象复用,它们可增强系统的易扩充性。
4.同时耦合程度也会增强可扩充性,如一个类不过多地依赖其他类,扩充这个孤立的类还是很容易的。
工具箱
一个应用程序经常会使用一个或多个被称为工具箱的预定义的类库中的类。工具箱是一组相关的、可复用的类的集合,这些类提供了通用的功能。工具箱的一个典型例子就是列表、关联表单、堆栈等类的集合。工具箱不强制应采用讴歌特定的设计,它们只是为你的应用提供功能上的帮助。工具箱强调的是代码复用,它是面向对象环境下的“子程序库”。
工具箱的设计应具有非特殊需求性,避免假设和依赖,否则会限制工具箱的灵活性,进而影响它的适用性和效率。
框架
框架是构成一类特定软件可复用设计的一组相互协作的类。一个框架能帮助建立适合不同领域的图形编辑器,像艺术绘画、音乐作曲和机械。另一个框架也许能帮助你建立针对不同程序设计语言和目标机器的编译器。而再一个也许能帮助你建立财务建模应用。你可以定义一个抽象类,定义一个子类,从而将一个框架定制为特定的应用。
框架规定了你的应用的体系结构。它定义了整体结构,类和对象的分割,各部分的主要责任,雷和对象怎么协作,以及控制流程。
框架预定义了这些设计参数,以便应用设计者集中精力于应用本身的特定细节。框架记录了应用领域的共同的设计决策。因而框架更强调设计复用,尽管框架包括具体的立即可用的子类。
如果说应用程序难以设计,那么工具箱就更难了,而框架则是最难的。框架设计者必须冒险决定一个要适应于该领域的所有应用的体系结构。任何对框架设计的实质性修改都会大大降低框架所带来的好处,因为框架对应用的最主要贡献在于它所定义的体系结构。因此设
计的框架必须尽可能地灵活、可扩充。
更进一步讲,因为应用的设计如此依赖于框架,所以应用对框架接口的变化是极其敏感的。当框架演化时,应用不得不随之演化。这使得松散耦合更加重要,否则框架的一个细微变化都将引起强烈反应。
设计模式和框架
1)设计模式比框架更抽象
框架能够用代码表示,而设计模式只有其实例才能表示为代
码。框架的威力在于它们能够使用程序设计语言写出来,它们不仅能被学习,也能被直接执行和复用。而本书中的设计模式在每一次被复用时,都需要被实现。设计模式还解释了它的意图、权衡和设计效果。
2)设计模式是比框架更小的体系结构元素
一个典型的框架包括了多个设计模式,而反之决非如此。
3)框架比设计模式更加特例化
框架总是针对一个特定的应用领域。一个图形编辑器框架可能被用于一个工厂模拟,但它不会被错认为是一个模拟框架。而本书收录的设计模式几乎能被用于任何应。当然比我们的模式更特殊的设计模式也是可能的(如,分布式系统和并发程序的设计模式),尽管这些模式不会像框架那样描述应用的体系结构。
框架变得越来越普遍和重要。它们是面向对象系统获得最大复用的方式。较大的面向对象应用将会由多层彼此合作的框架组成。应用的大部分设计和代码将来自于它所使用的框架
或受其影响。
怎样从多个设计模式选择适合自己的设计模式
- 考虑设计模式是怎样解决问题的
设计模式怎样帮助找到合适的对象、决定对象的粒度、指定对象接口以及设计模式解决设计问题的方法
- 浏览模式的意图部分
通读每个模式的意图,找出和你的问题相关的一个或多个模式,使用分类方法缩小你的搜查范围
- 研究模式怎样互相关联
以图的方式显示设计模式之间的关系。
- 研究目的相似的模式
- 检查重新设计的原因
检查重新设计的原因是否和设计模式有关,然后再找出哪些模式可以帮助你避免这些会导致重新设计的因素
- 考虑你的设计中哪些是可变的
这个方法与关注引起重新设计的原因刚好相反。它不是考虑什么会迫使你的设计改变,而是考虑你想要什么变化却又不会引起重新设计。独立变化的方面,你可以改变它们而又不会导致重新设计。
如何定义接口
为了让软件能长寿,其内部组织必须呈现有机次序,就是将软件本身的组织依“稳定”到“善变”程度层次分明的区分出来。
- 对象
对象用来划分出稳定与善变的界限,这个界限就通常称为接口。
对象的主要用途:把软件里局部而善变的部分包含在接口里面。当有必要时,就把接口内的善变的部分更换掉,让软件增添一份活力。
- 设计对象的目的是要得到明确的接口
设计对象的方法是将善变与稳定部分并无直接关联的东西隐藏在接口内,而接口上值留下与稳定部分有关的东西,这个过程称为“抽象”,即从接口内的善变部分抽出与接口外有关联的部分,摆在接口上,而无光的部分摆在接口内。
稳定与善变的部分划分得越理想,就越可得到简单的接口,对象就越易于更换,软件就越能蜕变成长。因此,软件的设计好坏就决定于程序员对稳定与善变的区分经验和能力。
- 设计对象最常用的方式
要向得到单纯的接口,最常见的方法是让对象所包装的细节部分具有高度紧密的相关性,也就是所谓的“凝聚性”,并且让内部的细节与外部的相关程度越低越好,就像陶渊明的室外桃源一样,除了少许信道之外尽可能与世隔绝开来。
结构化和面向对象:
1)以函数为中心,将常互相调用的有关函数结合起来构成叫独立的单元,统称为模块。而不考虑数据的角色。
2)以数据为中心,将直接处理到该数据的各有关函数结合起来,称为独立的单元统称为对象。
对象将数据及有关的函数包装起来,但允许对象内的函数能调用其他对象内的函数。
在20世纪70-80年代,人们采用第一种方法,称为结构化但并未成功。逐渐地,人们开始采用第二张方法,也就是以数据为中心,称为面向对象方法,到目前为止,已有良好的表现。
对象主要包括:
数据成员,统称为对象的数据属性。
成员函数,用来直接处理的程序,统称为对象的“方法”。
数据是函数处理的对象,且函数之间会互相调用。
举例:
1 | class |
此对象以数据为中心,并含有可以直接使用对象内部数据的相关函数draw()、paint()及move()。对象的函数和函数之间也可以互相调用,当然也可以调用其他对象内的函数(委托)。
对象的函数互相调用的情形相当复杂,但对象内的函数与其他对象函数的互相调用的情形,应尽量简单明确。这样,就可以得到单纯的对象接口,这样更有利于对象的更换,软件也更易于维护和成长。
例如:
1 | interface(circle) |
上面这段代码说明别的对象只能调用Circle对象的draw()及move()函数,而禁止调用其他的函数如paint(),更不能存取对象内的数据值。次对象和其他对象沟通通过interface接口而隐藏自己的数据属性和内部的细节,接口内也可操作固定死的对象数据。这样对象的接口就变成了善变与稳定部分的明确界限了。
接口是用于保存对象开放的部分或全部函数的指针集合,这部分函数是善变的数据的一个包装,抽象出来的稳定的部分。
在OOP程序中,通常借由下述两项定义来叙述对象:
1)类定义 —– 叙述对象内部含有哪些数据成员,以及含哪些有关的函数。
2)接口定义 —– 叙述对象内的函数中,有哪些是允许别的对象经由此接口而调用的。如何让别的对象知道与此对象沟通。
1 | interface(IA) |
也可以多个类实现同一个接口。
对象互换:
1 | interface(IA) |
这个程序复用了prin_area()函数,也就是说,print_area()可以和任何支持IA接口的对象沟通。原来pi指向circle的对象,将pi所指的对像换成rectangle的对象时,print_area()仍然可以执行,这个print_area()就像手机,而circle和rectangle就像两个不同的发音设备,一个是耳机一个是音响,耳机和音响都能插入手机(即接口),耳机和音响都有个和手机匹配的3.5mm的音频插头。再在比如家里的灯泡坏了,只需要换一个同接口的灯泡就可以,不管新的灯泡的发的是红光还是蓝光。
这里的耳机和音响,还是红灯和蓝灯,他们两两之间都有一个共性,前者是都有3.5mm的音频插头,后者是都有相同的接触座,这就是他们的共性,这些共性被抽象出来形成对外的接口,而他们一个发蓝光一个发红光的特性被隐藏在对象内部,形成对象的数据属性。
- 以接口实现多态
具有相同接口的一群对象,称之为多态对象。多态对象是可以互换的

一元硬币、五元硬币、十元硬币,都有可以被售票机识别的接口,ICoin接口value()函数。而且各个对象实现接口的都不相同,一元硬币调用ICoin接口的value()函数时返回1,五元硬币调用ICoin接口的value()函数时返回5,十元硬币调用ICoin接口的value()函数时返回10。
多态对象常存于一个数组或一个链表里,由次数组或链表,可知推销部门包括一个1圆硬币、一个5圆硬币和一个10圆硬币。因他们为同一部门的人员,故宜摆于同一数组或链表中。然而他们却不同类。
多态性能提供软件设计者极大的弹性与方便,因为计算机会根据对象的类而自动寻找适当的函数。

一般的售票机程序,会用if else判断,当售票机收到1园的硬币就加1,收到5圆的硬币就加5,如果下次国家又发行了一种20圆的硬币,那就要改售票机计费的程序了,非常麻烦。而如果是使用多态的售票机,完全不用改售票机的程序,因为售票机识别的是硬币,只要是符合ICon这个接口的硬币都可以接收。所以工厂只需要根据硬币该有的特性(ICon接口)把硬币造出来,那么这个硬币就能够被售票机识别。
这是多态性带来的好处,让售票机类既简洁又清晰
1 | // 硬币接口 |
- 一个类可以同时具有多个接口
就像一家餐厅,不仅可以提供堂食窗口,也可以外卖窗口。为来自现场和网上不同的顾客服务。

因此比较新的计算机编程语言,如VB、JAVA、C#等纷纷采用“类”与“接口”分开定义,让一个对象可提供多个不同的接口,呈现多面性的对象。
- 以OOPC实现接口设计
代码仓库:http://gitea.880755.xyz/private/oopc.git
- 集合对象
当一个类及其对象能容纳多态性对象时,我们通常称之为集合类或对象。
集合对象分两种储存多态类的方式:
顺序存储(table):采用数组,缺点是必须在创建对象时确定可容纳多态对象的容量,删除时麻烦,优点是添加时效率高。
链式存储(list):采用单链表,缺点是添加时动态内存分配效率低,优点是灵活添加删除方便,基本没有容量限制。
树形(tree):不讨论。
集合对象都具有的特点:如“菜篮子”般,能装各种蔬菜水果,简而言之,集合对象能包含多态对象,凡是具有相同接口的对象皆为多态对象。
示例:菜篮子
1 | // 菜篮子接口 |
接口与类定义的差异在于:接口只含有成员函数,而无数据成员。
接口通常放于类的第一个成员,使用接口时须将对象强转成AI接口类型,通过接口类访问函数。不然通过对象访问就需要,pr->IA.init()访问。

- 现实世界皆是一个个对象,软件实现面向对象才能和现实世界的事务心心相印

对象就是在代码中把物体拟人化(和语文书上的拟人化一个意思),让死的物体不仅有属性,还要让死的物体会说话,让对象和对象直接都可以说话沟通。
- 类
类就是一个模具,程序员首先需要设计模具,在用这个模具做出一个个属性和行为相近的对象。人们只要针对类去加以描述就等于描述了所有的对象了。
一旦软件人员描述好了类,计算机在执行期间,就把类视为模子(Template),依据模子而生成软件对象,并且安排对象之间的互相沟通与合作,那么,软件系统就能提供给用户各式各样的服务了。


1.一类对象可以有不同值的属性,但一类对象的行为肯定是一样的。
2.通常,对象将其属性封装起来,避免外接的影响。所以,对象必须负责维护本身的属性,即必须提供函数来维护对象的属性。确保别人只能按照自己设计的合法的规则来读取或修改它。
- 为什么要描述类间的关系
在面向对象思维下,人们把软件视为一群对象的互相沟通合作。在行为方面,对象会互相传递信息,例如银行用户对象会送信息 账户,问他的银行存款余额。在结构方面,对象间会有其组合结构,例如一个用户能拥有多个账户,这意味着:一个用户对象可能会连接(Link)到多个账户对象。再如一个,车体 对象可能会连接到多个“轮胎”对象。在开发软件时,不仅需要描述对象的属性(Data)和行为(Behavior),而且必须描述对象之间的沟通及其结构面的连接关系。在上一节里已经说明了,在OOPC程序里,必须定义类来叙述对象,所以在类定义里,不仅需要定义类的内部属性及函数,还得定义类间的连接关系。这种连接关系包括组合(Composition)关系及结合(Association)关系等。
作者和书示例:
1 | class(author) |



- 对象的结合关系
上面的book对象和作者对象是包含和被包含的关系,一旦book对象被删除,作者对象也就被删除了。
而一个作者可以写很多本书,如果一本书本删除了,作者也被删除了就不合理,可以将书对象和作者对象设计成两个独立的对象,在创建对象后再通过代码将两个对象关联起来。

1 | class(book) |
将对象后期结合,时一个对象不再对另一个对象负责,他们都是独立的个体。不是共生共灭的关系。
- 如何得到类
较常用的对象设计方法:
1)人
人是任何系统的重要角色,通常是最容易找到的对象。例如:公司有5位销售员,各负责一个地区的任务,并与该区的用户联络。从这段叙述中,就可发现两种对象-销售员及用户,每一位销售员皆是对象;同样地,每一个用户皆是对象。
2)地方
地点是很容易发现的对象。例如:您从订单上看到产品将送达的目的地、用户的所在地。再拿旅行社行程来当例子,各旅行团将在不同的观光地区停留,各观光地点皆是对象。
3)事物
在可摸到或看到的实物中,也容易找到与系统有关的对象,例如:产品是销售系统及生产系统的明显对象,原料细项是生产及库存系统的重要对象。就饭店管理系统而言, “房间”是重要对象。“书本”及“志”为图书馆或书店管理系统的明显对象。
4)事件
在企业界最常见的事件是“交易”,当事件发生时,我们会去记录它发生的时刻、有关金额等。这种我们所关心的事件也常是重要的对象。值得注意的是,这些事件是已发生的,为一项行为或动作。所以在文档中,常是一个句子的动词。例如:今天共有3种原料已降至安全存量之下,所以共订购3种原料。这每一“订购”件皆为对象。就飞机场的控制系统而言,每次飞机“起飞”或“降落”皆是重要对象。而“提款”及“转账”皆为银行系统的重要对象。“挂号”及“就诊”为医疗系统的对象。
5)构想
与企业营运或机构管理有关的“构想”或各种“计划”或其他概念;这些无形的,但决定企业活动的构想,常是重要对象。例如:公司正拟定3种广告策略,其中每一种策略就是企业营销系统的重要对象。这家公司正透过2种渠道与小区居民沟通,这里的渠道也是概念性的对象。
6)外部系统或设备
软件系统常会与其他系统沟通,互相交换信息。有时也由外部设备取得交易数据或把处理结果送往外部设备。这些外部系统或设备也是对象。例如:库存系统与采购系统会互相沟通,对库存系统而言,采购系统是对象:反之,对采购系统而言,库存系统则为对象。如果收款机直接把交易数据传送给销售系统,则收款机是此销售系统的对象。如果股票系统直接把数据传送到交易市场的电视显示屏上,则对股票系统而言,电视显示屏是对象。
7)组织单位
企业机构的部门或单位。例如,在学校管理系统中,教务处及训导处等单位皆是对象。
8)结构
有些对象会包含其他对象。所以在对象中常能找到其他对象。例如,在学校的组织单位–教务处,含有小对象如注册组及学籍组等。在汽车对象中可找到引擎、轮胎及座椅等对象。在“房屋”对象中,会发现到厨房、客厅、沙发等对象。
以上介绍的是常用的寻找对象方法,会寻找对象之后,就必须将对象分门别类,并且了解类之间的关系,以便把它们组织起来。例如,在公司的人事结构中,可发现人因扮演角色的不同而分为不同种类的对象,如推销员、司机、经理等等。汽车可分为跑车、巴士、旅行车等不同种类的对象。
- 概念
由于概念是非常稳定的。所以, OOA鼓励大家以概念为中心,基于概念而得出类图,再以类为单元,将计算机程序里的函数和指令纳入类里。于是呈现出一个美好的景象:善变的指令被封装于稳定的类(概念)里。这也达到了O0A所追求的另一目标:封装(Encapsulation)
大家都知道封装良好的产品常常更令人喜爱。


- 用例(use case)和功能
用例在系统的众多功能当中,属于直接提供用户服务的部分。例如麦当劳餐厅可视为一个系统,它具有许多功能,像“卖汉堡”、“采购蔬菜”、“炸薯条”、“卖咖啡”、“提供厕所”、“提供小孩游戏”、“烘焙咖啡”,等等。其中有一小部分是用户能看得见、感觉得到又觉得有意义的服务,就是用例。而系统的其他功能就不称为用例,而只是一般的系统功能罢了。
用例的实例是场景,至于一般的类,其实列是对象。
Use case类 — 实例是Scenario
一般功能类 —– 实例是Object
1.描述该服务的名称及返回的信息类型,它描述What
2.描述服务过程中,用户与系统之间有哪些交互(即两者的对话流程) ,其描述How和When。但是请留意,这个How不是员工做汉堡的How,而是用户如何与系统最好交互) 的How,请你务必区别开它们。
3.描述用户(又称为Use Case的Actor)的角色,它描述Who.

一个用例就是一连串通过系统的事件(a specific flow of
events through system)。其包括系统对这些事件的反应,以及用户对事件的反应,即用例也描述了系统的外观行为。所以,可藉由用例来表达系统的行为需求。


一个系统就好像一个系统,从外观来看,一个足球表面有许多用列,而一个用例就代表一个使用场景,会由一个或多个和对象共同支撑。

足球员(用户)关心的是产品(系统)能否满足他的目的并且方便使用。
以上是从足球员(用户的角度看),仅仅看到的是系统(足球)的外观。如果改从工程师的角度看,一个个用例就代表一群对象联合执行一项服务。每一个用例的幕后都有一群对象互相沟通与合作,好像看到了足球的内部结构。

一个对象可参与许多个不同的用例,让对象有更多 复用 (Reuse)的机会,则对象的可靠度提升了,复用机会也随之提升,整个系统的质量也就提升了。UML用例图让我们在建模阶段就将收益与成本紧密连结起来,这对系统在市场上的成功与失败至关重要。
开发对象是成本、付出,销售功能和用例是收益、获得。

演奏者是对象,“演奏蓝色多瑙河”是用例,听众是用户。
众多演奏者和“蓝色多瑙河”、“田园交响曲”构成一个系统,系统的外观是“演奏蓝色多瑙河”、“演奏田园交响曲”。
对系统:构建一个系统是成本,听众收听乐曲是收益。
归纳上面所述,用例是收益与成本的衔接点。在收益方面,用例确保了系统的可用性。


- 用例间的关系
包含和扩充的关系

包含关系(买汉堡包基础用例包含结账包含用例):


扩充关系(买汉堡包基础用例扩充赠送玩家扩充用列):
当用户是儿童用户时引发赠送玩具流程。

包含用例是必须执行的,扩充用例是当特定条件满足才会引发流程。分别表示常态和特定环境。
- UML序列图的意义
在上一章介绍过,用例(Use Case)是收益与成本的衔接点。在收益方面,用例引导我
们用心探索围绕“使用”的一连串“为什么”的问题,从而厘清了:
1.系统提供各种功能的目的
2.用户跟系统的交互情形
用例让软件人员暂时不考虑软件系统内部的行为和结构,而专注于理清用户“为什么”去“使用”这个系统。

- 聊天软件状态图示例:
1 | @startuml |

- 本文作者: 龙兄嵌入式
- 本文链接: https://hexo.880755.xyz/1970/01/01/zblog/download/87.OOPC嵌入式软件开发/