积木

No sub title

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  140 Posts :: 1 Stories :: 11 Comments :: 0 Trackbacks

常用链接

留言簿(1)

我参与的团队

搜索

  •  

最新评论

阅读排行榜

评论排行榜

#

在描述对象之间的交互时,常会用到时序图和协作图,它们用来描述对象以及对象之间
的消息。时序图是以时间为序的表示方法,主要用来描述对象之间的时间顺序。
----------------------------------
时序图(Sequen四Diagram) 描述了对象之间传送消息的时间顺序,它用来表示用例中
的行为顺序。当执行 个用例行为时,时序图中的每条消息对应了 个类操作或状态机中引
起转换的触发事件。
时序图包含了4个元素,分别是对象(0均ect)、生命线(L悔line)、消息(Message) 和
激活(Activation)。
1  对象
时序图中对象的符号和对象图中对象所用的符号一样,都是使用矩形将对象名称包含起来,
并且对象名称下有下划线。将对象置于时序图的顶部意味着在交互开始的时候
对象就已经存在了,如果对象的位置不在顶部,那么表示对象是在交互的过程中被创建的。
2  生命线
生命线(Lifeline) 是一条垂直的虚线,表示时序图中的对象在-段时间内的存在e 每个
对象的底部中心的位置都带有生命线。 生命线是-个时间线,从时序图的顶部一直延伸到底
部,所用的时间取决于交互持续的时间因对象与生命线结合在一起称为对象的生命线,对象
的生命线包含矩形的对象图标以及图标下面的生命线。
提示: 实际上,对象的生命线可以代表一组对象.
3  消息
消息(Message) 定义的是对象之间某种形式的通信,它可以激发某个操作、唤起信号
或导致目标对象的创建或撤销。消息序列可以用两种图来表示:时序图和协作图。其中,时
序图强调消息的时间顺序,而协作图强调交换消息的对象间的关系。
消息是两个对象之间的单路通信,从发送方到接收方的控制信息流。消息可以用于在对
象间传递参数。消息可以是信号,即明确的、命名的、对象间的异步通信;也可以是调用,
即具有返回控制机制的操作的同步调用。
在UML中,消息使用箭头来表示,箭头的类型表示了消息的类型,时序图中常用的消息符号如下:

注意:消息在生命线上所处的位置并不是消息求生的准确时间.只是一个相对的位里.如果一个消息位
于另一个消息的上方,只说明它先于另一个消息被发送。
.4激活
时序图可以描述对象的激活(Activation) 和去激活(Deactivation)。激活表示该对象被
占用以完成某个任务,去激活指的是对象处于空闲状态,在等待消息。在UML中,为了表
示对象是激活的,可以将对象的生命线拓宽成为矩形。其中的矩形称为激活
条或控制期,对象就是在激活条的顶部被激活的。对象在完成自己的工作后被去激活,这通
常发生在一个消息箭头离开对象生命线的时候。
----------------------------------
如果要撤销一个对象,只要在其生命线终止点放置一个"X"符号即可,该点通常是对
删除或取消消息的回应。
----------------------------------
时序图建模
一般情况下,会有很多时序图,其中的一些是主要的,另一些用来描述可选择的路径或
例外条件,可以使用包来组织这些时序图的集合,并给每个图起一个合适的名字,以便与其
他图相区别。
按时间顺序对控制流建模,要遵循如下策略。
(1) 设置交互的语境,这些语境可以是系统、子系统、操作、类、用例或协作的脚本。
(2) 通过识别对象在交互中扮演的角色,设置交互的场景。以从左到右的顺序将对象放
到时序图的上方,其中较重要的放在左边,与它们相邻的对象放在右边。
(3)为每个对象设置生命线。通常情况下,对象存在于整个交互过程中。对于那些在交
互期间创建和撤销的对象,在适当的时刻设置它们的生命线,并用适当的构造型消息显式地
说明它们的创建和撤销。
(4) 从引发某个消息的信息开始,在生命线之间画出从顶到底依次展开的消息,显示每
个消息的特性(如参数)。若有需要,解释交互的语义。
(5) 如果需要可视化消息的嵌套或实际计算发生时的时间点,可以用激活修饰每个对象
的生命期。
(6) 如果需要说明时间或空间的约束,可以用时间标记修饰每个消息,并附上合适的时
间和空间约束。
(7) 如果需要形式化地说明某控制流,可以为每个消息附上前置和后置条件。
一个单独的时序图只能显示一个控制流,通常说来,一个完整的控制流肯定是复杂的,
所以,将 个大的流分为几个部分放在不同的图中是比较合适的。
posted @ 2013-11-12 21:28 Jacc.Kim 阅读(911) | 评论 (0)编辑 收藏

活动图是UML用于对系统的动态行为建模的另一种常用工具,它描述活动的顺序,展
现从一个活动到另一个活动的控制流.活动图在本质上是一种流程图。
-------------------------------
什么是活动?活动图与状态图的区别是什么?
活动是某件事情正在进行的状态,既可以是现实生活中正在进行的某 项工作,也可以是软
件系统某个类对象的一个操作。活动在状态机中表现为由一系列动作组成的非原子的执行过程。
虽然活动图与状态图都是状态机的表现形式,但是两者还是有本质区别·活动图着重表
现从一个活动到另一个活动的控制流,是内部处理驱动的流程:而状态图着重描述从一个状
态到另一个状态的流程, 主要有外部事件的参与。
-------------------------------
活动图的图形表示
在UML中,活动图表示成圆角矩形,与状态图的圆角矩形相比,活动图的矩形的圆角
更柔和,看上去接近椭圆。活动图的图标包含对活动的描述(如活动名)。如果一个活动引发
下一个活动,两个活动的图标之间用带箭头的直线连接。 与状态图类似,活动圈也有起点和
终点,表示法和状态图相同。
活动图中还包括分支与合并、分叉与汇合等模型元素。 分支与合并的图标和状态图中判定
的图标相同,而分叉与汇合则用一条加粗的线段表示。
-------------------------------
活动图与流程图的区别
虽然活动图描述系统使用的活动、判定点和分支,看起来和流程图没什么两样,并且传
统的流程图所能表示的内容,大多数情况下也可以使用活动图表示,但是两者是有区别的,
不能将两个概念混淆。
活动图与流程图的区别如下。
(1)流程阁着重描述处理过程,它的主要控制结构是顺序、分支和循环,各个处理过程
之间有严格的顺序和时间关系;而活动图描述的是对象活动的顺序关系所遵循的规则,它着
重表现的是系统的行为,而非系统的处理过程。
(2) 活动图能够表示并发活动的情形,而流程图不能。
(3) 活动图是面向对象的,而流程图是面向过程的.
-------------------------------
活动图的组成元素
UML的活动图中包含的图形元素有动作状态、 活动状态、动作流、分支与合并、分叉与
汇合、泳道和对象流等。
4  分支与合并
动作流一般会自动进行控制转换,直到遇到分支.分支在软件系统流程中很常见,它­
般用于表示对象类所具有的条件行为。一个无条件的动作流可以在一个动作状态的动作完成
后自动触发动作状态的转换以激发下一个动作状态,而有条件的动作流则需要根据条件,即
一个布尔表达式的真假来判定动作的流向.条件行为用分支和合并表达。
在活动图中分支与合并用空心小菱形表示。分支包括一个入转换和两个带条件的出转
换,出转换的条件应当是互斥的,这样可以保证只有一条出转换能够被触发。合并包括两个
带条件的入转换和一个出转换,合并表示从对应的分支开始的条件行为的结束。
5  分支与汇合
对象在运行时可能会存在两个或者多个并发运行的控制流,为了对并发的控制流建馍,
在UML中寻|入了分叉与汇合的概念,分叉用于将动作流分为两个或者多个并发运行的分支,
而汇合则用于同步这些并发分支,以达到共同完成一项事务的目的。
分叉可以用来描述并发线程,每个分叉可以有一个输入转换和两个或多个输出转换,每
个转换都可以是独立的控制流。
汇合代表两个或多个并发控制流同步发生,当所有的控制流都达到汇合点后,控制才能
继续往下进行。每个汇合可以有两个或多个输入转换和一个输出转换。
分叉和汇合都使用加粗的水平线段表示。
6  泳道
泳道将活动图中的活动化分为若干组,并把每一组指定给负责这组活动的业务组织.&P
对象。 在活动图中,泳道区分了负责活动的对象,它明确地表示了哪些活动是由哪些对象进
行的。 在包含泳道的活动图中,每个活动只能明确地属于一个泳道。
在活动图中,泳道用垂直实线绘出,垂直线分隔的区域就是泳道。在泳道上方可以给出
泳道的名字或对象(对象类〕的名字,该对象(对象类〉负责泳道内的全部活动。泳道没有
顺序,不同泳道中的活动既可以顺序进行也可以并发进行,动作流和对象流允许穿越分隔线。
7 对象流
对象流是动作状态或者活动状态与对象之间的依赖关系,表示动作使用对象或者动作对
对象的影响。 用活动图描述某个对象时,可以把涉及到的对象放置在活动图中并用一个依赖
将其连接到进行创建;修改和撤销的动作状态或者活动状态上,对象的这种使用方法就构成
了对象流。
对象流中的对象有如下特点·
(1)  个对象可以由多个动作操纵,
2)一个动作输出的对象可以作为另一个动作输入的对象:
(3)在活动图中,同一个对象可以多次出现,它的每-次出现表明该对象正处于对象生
存期的不同时间点.
在活动图中,对象流用带有箭头的虚线表示。如果箭头从动作状态出发指向对象,则表
示动作对对象施加了一定的影响。施加的影响包括创建、修改和撤销等。如果箭头从对象指
向动作状态,则表示该动作使用对象流所指向的对象。
-------------------------------
活动的分解
一个活动可以分为若干个动作或子活动,这些动作和子活动本身又可以组成一个活动
图。不含内嵌活动或动作的活动称之为简单活动:嵌套了若干活动或动作的活动称之为组合
活动,组合活动有自己的名字和相应的子活动图。
-------------------------------
活动图建模技术
在系统建模的过程中,活动图能够附加到任何建模元素中以描述其行为,这些元素包括
用例、类、接口、节点、协作、操作和方法等。通常来说,用活动图对工作流建模可遵循如
下步骤:
(1)识别要对工作流描述的类或对象a 找出负责工作流实现的业务对象,这些对象可以
是显示业务领域的实体,也可以是一种抽象的概念和事物。找出业务对象的目的是为每一个
重要的业务对象建立泳道。
(2) 确定工作流的初始状态和终止状态,明确工作流的边界。
(3)对动作状态或活动状态建模。找出随时间发生的动作和活动,将它们表示为动作状
态或活动状态。
(4) 对动作流建模。对动作流建模时可以首先处理顺序动作,接着处理分支与合并等条
件行为,然后处理分叉与汇合等并发行为。
(5) 对对象流建模。找出与工作流相关的重要对象,并将其连接到相应的动作状态和活
动状态。
(6) 对建立的模型进行精化和细化。
posted @ 2013-11-12 00:42 Jacc.Kim 阅读(518) | 评论 (0)编辑 收藏

状态图是系统分析的一种常用工具,它通过建立类对象的生存周期模型来描述对象随时
间变化的动态行为。
----------------------------
状态机是展示状态与状态转换的图。在面向对象分析与设计中,对象的状态、状态的转
换、触发状态转换的事件、对象对事件的响应(即事件的行为〉都可以用状态图来描述。
UML用状态机对软件系统的动态特征建模。 通常一个状态机依附于一个类,并且描述­
个类的实例(即对象的状态机包含了一个类的对象在其生命期间所有状态的序列以及对象对
接收到的事件所产生的反应。
----------------------------
状态机由状态、转换、事件、活动和动作5部分组成。
(1)状态表示一个模型在其生存期内的状况,如满足某些条件、执行某些操作或等待某
些事件。一个状态的生存期是有限的一个时间段.
(2) 转换表示两个不同状态之间的联系,事件可以触发状态之间的转换.
(3)事件是在某个时间产生的,可以触发状态转换的,如信号、对象的创建和销毁、超
时和条件的改变等。
(4) 活动是在状态机中进行的一个非原子的执行,由一系列动作组成。
(5) 动作是一个可执行的原子计算,它导致状态的变更或者返回一个值。
状态机不仅可以用于描述类的行为,也可以描述用例、协作和方法甚至整个系统的动态行为。
----------------------------
状态图由表示状态的节点和表示状态之间转换的带箭头的直线组成。若干个状态由一条
或者多条转换箭头连接,状态的转换由事件触发。模型元素的行为可以由状态图中的一条通
路表示,沿着此通路状态机随之执行了一系列动作。
组成UML的图形元素有状态、转换、初始状态、终结状态和判定等。
(1) 状态由一个带圆角的矩形表示,状态图的图标可以分为3部分: 名称、内部转换和嵌套
状态图。
        a) 名称表示状态的名字,通常用字符串表示
        b) 内部转换。在内部转换中可以包含进入或者走出此状态应该执行的活动或动作,它
们将响应对象所接收到的事件,但是不改变对象的状态。
        c) 嵌套状态图。状态图中的状态有两种·一种是简单状态,简单状态不包含其他状态;
一种是组合状态,组合状态是包含子状态的状态。在组合状态的嵌套状态图部分包含的就是
此状态的子状态。
(2) 转换用带箭头的直线表示,一端连接源状态,即转出的状态,箭头一端连接目标状态,
即转入的状态。转换可以标注与此转换相关的选项,如事件、动作和监护条件。
注意: 如果转换上没有标注触发转换的事件,则表示此转换为自动进行.
(3) 每个状态图都应该有 个初始状态,此状态代表状态图的起始位置。初始状态只能作为
转换的源,而不能作为转换的目标。起始状态在一个状态图中只允许有一个,用一个实心的
圆表示。
(4) 终止状态是模型元素的最后状态,是一个状态图的终止点。终止状态只能作为转换的目
标,而不能作为转换的源。终止状态在一个状态图中可以有多个,它用 个含有实心圆的空
心圆表示。
(5) 判定处在状态图中这样一个位置: 工作流在此处按监护条件的取值而发生分支。 判定用
空心小菱形表示。因为监护条件为布尔表达式,所以通常条件下的判定只有一个入转换和两
个出转换。根据监护条件的真假可以触发不同的分支转换。
----------------------------
入口动作和出口动作表示进入或退出某个状态所要执行的动作。入口动作用"entry/要执
行的动作"表达,而出口动作用"exit/要执行的动作"表达。
----------------------------
事件表示在某一特定的时间或空间出现的能够引发状态改变的运动变化,如接收到的从
一个对象对另一个对象发送的信号、某些值的改变或一个时间段的终结。事件是一个激励的
出现, 它定义一个触发子以触发对象改变其状态,任何影响对象的事物都可以是事件。
事件有多种,大致可分为入口事件、出口事件、动作事件、信号事件、调用事件、修改
事件、时间事件和延迟事件等儿种。
1  入口事件
入口事件表示 个入口的动作序列,它在进入状态时执行。入口事件的动作是原子的,
并且先于人和内部活动或转换。
2  出口事件
出口事件表示一个出口的动作序列,它在退出状态时执行。出口事件也是原子的,它跟
在所有的内部活动之后,但是先于所有的出口转换。
3  动作事件
动作事件也称为"do 事件".它表示对一个嵌套状态机的调用。与动作事件相关的活动
必定引用嵌套状态机,而非引用包含它的对象的操作。
4  信号事件
信号是两个对象之间的通信媒介,信号的接收是信号接收对象的一个事件。 信号分为异
步单路通信和双路通信.在异步单路通信中,发送者是独立的,它不必等待接收者处理信号.
在双路通信模型中,至少在每个方向上都要有一个信号,这就是所谓的多信号B 在信号事件
中,发送者和接收者可以是同一个对象。
5  调用事件
调用事件是一个对象对调用的接收,这个对象用状态的转换而不是用固定的处理过程实
现操作。调用事件至少涉及两个以上的对象,一个对象请求调用另 个对象的操作。 对调用
者来说,一旦调用的接收对象通过囱事件触发的转换完成了对调用事件的处理或调用失败,
而没有进行任何状态转换,则控制返回到调用对象。 调用事件既可以为同步调用,也可以为
异步调用。如果调用者需要等待操作的完成,则是同步调用,否则是异步调用.
6  修改事件
修改事件依靠特定属性值的布尔表达式所表示的条件的满足来触发状态的转换. 它表示
了一种具有时间持续性的并且可能是涉及全局的计算过程,测试修改事件的代价可能很大,
因为原则上修改事件是持续不断的。
监护条件与修改事件的区别在于监护条件只是在引起转换的触发器事件触发时和事件
接收者对事件进行处理时被赋值 次,而修改事件则可以被多次赋值直到条件为真,多次赋
值满足条件后转换也会被激发。
7  时间事件
时间事件代表时间的流逝。
8  延迟事件
延迟事件是在本状态不处理,要推迟到另外一个状态才处理的事件。 通常,在一个状态
生存期出现的事件若不被立即响应就会丢失.但是,这些未立即触发转换的事件可以放在一
个内部的延迟事件队列中,等待需要时触发或者撤消, 如果一个转换依赖一个存在于内部延
迟事件队列中的事件,则事件立即触发转换:如果存在多个转换,则内部延迟事件队列中的
第一个事件将有优先触发相应转换的权利。
----------------------------
转换表示当一个特定事件发生或者某些条件得到满足时,一个源状态下的对象在完成一
定的动作后将发生状态转变,转向另 个称之为目标状态的状态。当发生转换时,转换进入
的状态为活动状态,转换离开的状态变为非活动状态.

转换通常分为外部转换、内部转换、完成转换和复合转换4种。一个转换一般包括5部
分的信息:源状态、目标状态、 触发事件、监护条件和动作。

1  外部转换
外部转换是一种改变对象状态的转换,它是战常见的一种转换。外部转换用从源状态到
目标状态的箭头表示。
2  内部转换
内部转换有一个源状态但是没有目标状态,它转换后的状态仍旧是它本身。 内部转换的
激发规则和改变状态的外部转换的激发规则相同,如果一个内部转换带有动作,动作也要被
执行。内部转换用于对不改变状态的插入动作建立模型,例如建立帮助信息。
内部转换和自转换不同, 自转换是离开本状态后重新进入
该状态,它会激发状态的入口动作和出口动作的执行;而内部转换自始至终都不离开本状态,
所以没有出口或入口事件,也就不执行入口和出口动作。内部转换和入口动作或出口动作采
用相似的表示方法。
4  复合转换
复合转换由简单转换组成,这些简单转换通过分支判定、分叉或接合组合在一起.前
面所讲的由判定参与的转换就是复合转换.除了简单的两个分支的判定,还有多条件的分
支判定.多条件的分支判定又分为链式的和非链式的分支。
5  触发事件
状态机描述了对象的具有事件驱动的动态行为,对象动作的执行、状态的改变都是以特
定事件的发生为前提的,触发事件就是能够引起状态转换的事件。触发事件可以是信号、调
用和时间段等。
6  监护条件
转换可能具有一个监护条件,监护条件是触发转换必须满足的条件,它是一个布尔表达
式。 当事件被触发时,监护条件被赋值. 如果布尔表达式的值为真,那么转换被触发;如果
布尔表达式的值为假,则不会引起转换。 监护条件只能在触发事件发生时被赋值一次,如果
在转换发生后监护条件才由假变为真,那么转换也不会被触发。
从 个状态引出的多个转换可以有同样的触发器事件,但是每个转换必须具有不同的监
护条件。当其中一个监护条件满足时,触发器事件会引起相应的转换,监护条件应该确保
个触发器事件的发生能够引起某些转换。
7  动作
动作是一组可执行语句或者计算处理过程。动作可以包括发送消息给另一个对象、操作
调用、设置返回值、创建和销毁对象等。动作也可以是一个动作序列,即一系列简单的动作
的组合。动作是原子的,不可中断的,动作或动作序列的执行不会被同时发生的其他动作影
响或终止。 动作的执行时间非常短,与外界事件所经历的时间相比是可以忽略的,因此,在
动作的执行过程中不能再插入其他事件.
整个系统可以在同一时间执行多个动作。动作在它的控制线程中是原子性的,一旦开始
执行就必须执行到底并且不能与同时处于活动状态的动作发生交互作用。与系统处理外部事
件所需要的反应时间相比,动作的执行过程应该简洁到能做出实时响应。
----------------------------
状态图建模技术
状态图一般用于对系统中的某些对象,比如类、用例和系统的行为建模。建模的时候要
找出对象所处的状态、 触发状态改变的动作,以及对象状态改变时应执行的动作.具体的建
模步骤如下。
(1)找出适合用模型描述其行为的类。
(2)确定对象可能存在的状态。
(3)确定引起状态转换的事件。
(4) 确定转换进行时对象执行的相应动作,
(5) 对建模的结果进行相应的精化和细化。
posted @ 2013-11-11 22:33 Jacc.Kim 阅读(432) | 评论 (0)编辑 收藏

类图(ClassDiagram) 是描述类、接口、协作以及它们之间关系的图,用来显示系统中
各个类的静态结构。类图是一种模型类型,确切地说,是一种静态模型类型。
类图是面向对象系统建模中最常用的图,它是定义其他图的基础,在类图的基础上,可
以使用状态图、协作图、组件图和配置图等进一步描述系统其他方面的特性。
类图包含7 个元素:类(Class)、接口(1nterface )、协作(Collaboratio川、依赖关系
( Dependency )、泛化关系(Generalization)、关联关系(Association)以及实现关系(Realization) 。
说明:其实还有聚合、组合。
另外,所谓的协作,其实就是指各类、接口间存在的各种关系。因此,各类间一般不是孤立存在的。
注意:
A) 在UML中,公有类型用"+"表达,私有类型用"-"表达,而受保护类型则用"# "表达。UML的类中不存在
默认的可见性,如果没有显示任何一种符号,就表示没有定义该属性的可见性。
B) 。类中操作的可见性主要包括公有(PubliC)、私有(Private)、受保护(Protected)
和包内公有(Package) 4种,分别用"+"、"-"、"#"和"~"来表示。
其中,只要调用对象能够访问操作所在的包,就可以调用可见性为公有的操作;只有属
于同一个类的对象才可以调用可见性为私有的操作,只有子类的对象才可以调用父类的可见
性为受保护的操作:只有在同一个包里的对象才可以调用可见性为包内公有的操作。
----------------------
UML定义了4种基本依赖类型,分别是使用(Usage) 依赖、抽象CAbstraction) 依赖、
授权(Permission) 依赖和绑定CBinding) 依赖.其中,使用依赖是类中最常用的依赖。
在实际建镇中.3 种情况下产生使用依赖:客户类的操作需要提供者类的参数:客户类的
操作返回提供者类的值;客户类的操作在实现中使用提供者类的对象。使用的构造型
包括调用和实例。在实际建模中,调用依赖和参数依赖较少被使用。发送依赖规定
客户把信号发送到非指定的目标,实例化依赖则规定客户创建目标元素的实例。
---------------------
关联关系(Association )
关联关系是一种结构关系,它指明一个事物的对象与另一个事物的对象之间的联系。也
就是说,关联描述了系统中对象或实例之间的离散连接。关联的任何一个连接点都叫做关联
端,与类有关的许多信息都附在它的端点上。在UML中,关联关系用一条连接两个类的实
线表示。
---------------------
聚合(Aggregation )。聚合关系是一种特殊类型的关联,它表示整体与部分关系的
关联。简单的说,关联关系中一组元素组成了一个更大、更复杂的单元,这种关联关系就是
聚合。聚合关系描述了"has a" 的关系。在UML中,聚合关系用带空心菱形头的实线来表
示,其中头部指向整体。
---------------------
组合关系(Composition)。组合关系是聚合关系中的一种特殊情况,是更强形式的
聚合,又被称为强聚合e 在组合中,成员对象的生命周期取决于聚合的生命周期,聚合不仅
控制着成员对象的行为,而且控制着成员对象的创建和解构。在U孔伍中,组合关系用带实
心菱形头的实线来表示,其中头部指向整体。
---------------------
导航性(Navigation)。导航性描述的是一个对象通过链(关联的实例〉进行导航访
问另一个对象,即对一个关联端点设置导航属性意味着本端的对象可以被另 端的对象访问。
可以在关联关系上加箭头表示导航方向。只在一个方向上可以导航的关联称为单向关联
(Unidirectional Association),用→条带箭头的实线来表示,如图6-23所示:在两个方向上都
可以导航的关联称为双向关联(Bidirectional Association),用一条没有箭头的实线来表示。
另外,使用导航性可以降低类间的精合度,这也是好的面向对象分析与设计的目标之一。
----------------------
对象图<ObjectDiagram) 描述的是参与交互的各个对象在交互过程中某一时刻的状态·
对象图可以被看作是类图在某一时刻的实例。 在U阻中,对象图使用的是与类图相同的
符号和关系,因为对象就是类的实例。
posted @ 2013-11-10 21:16 Jacc.Kim 阅读(378) | 评论 (0)编辑 收藏

1) 用例图包含6个元素,分别是:参与者(Actor)、用例(UseCase)、关联关系(Association) 、
包含关系(Include)、扩展关系(Extend) 以及泛化关系(Generalization)。

2) 参与者有三大类:系统用户、与所建造的系统交互的其他系统和一些可以运行的进程。
第一类参与者是真实的人,即用户,是最常用的参与者,几乎存在于每一个系统中。命
名这类参与者时,应当按照业务而不是位置命名,因为一个人可能有很多业务。例如汽车租
赁公司的客户服务代表,通常情况下是客户服务代表,但是如果他(她)自己要租车的时候,
就变成了客户,所以,按照业务而不是位置命名可以获得更稳定的参与者。
第二类参与者是其他的系统.例如汽车租赁系统可能需要与外部应用程序建立联系,验
证信用卡以便付款。 其中,外部信用卡应用程序是一个参与者,是另一个系统。因此在当前
项目的范围之外,需要建立与其他系统的接口。这类位于程序边界之外的系统也是参与者。
第三类参与者是一些可以运行的进程,如时间。当经过一定时间出发系统中的某个事件
时,时间就成了参与者。例如,在汽军租赁系统中,到了还车的时间客户还没有归还汽车,
系统会提醒客户服务代表致电客户。 由于时间不在人的控制之内,因此它也是一个参与者。
注意:参与者之间,还存在着一般化与特殊化的关系。一般用泛化关系来表示。具体表示法
同类的泛化关系相同。

3) 用例是外部可见的系统功能单元,这些功能由系统单元所提供,并通过-系列系统单元
与一个或多个参与者之间交换的消息所表达。用例的用途是,在不揭示系统内部构造的前提
下定义连贯的行为。
在系统层,用例表示整个系统对外部用户可见的行为。-个用例就像外部用户可以使用
的系统操作。但是,它又与操作不同,用例可以在执行过程中持续接受参与者的输入信息。

4) 识别用例
识别用例最好的方法就是从分析系统的参与者开始,考虑每个参与者是如何使用系统
的。使用这种策略的过程中可能会发现新的参与者,这对完善整个系统的建模有很大的帮助。
用例建模的过程就是一个法代和逐步精华的过程,系统分析者首先从用例的名称开始,然后
添加用例的细节信息。这些信息由简短的描述组成,它们被精华成完整的规格说明。
在识别用例的过程中,通过回答以下的儿个问题,系统分析者可以获得帮助。
(1)特定参与者希望系统提供什么功能。
(2)系统是否存储和检索信息,如果是,由哪个参与者触发。
(3)当系统改变状态时,是否通知参与者。
(4) 是否存在影响系统的外部事件。
(5) 哪个参与者通知系统这些事件。

5) 用例间的关系
用例除了与其参与者发生关联外,还可以具有系统中的多个关系,这些关系包括关联关系、
包含关系、扩展关系和泛化关系。应用这些关系的目的是为了从系统中抽取出公共行为和
其变体。
1  关联关系(Association )
关联关系表示参与者用例之间的通信。
2  包含关系(Include )
虽然每个用例的实例都是独立的,但是一个用例可以用其他的更简单的用例来描述。这
有点像通过继承父类并增加附加描述来定义一个类。 个用例可以简单地包含其他用例具有
的行为,并把它所包含的用例行为作为自身行为的一部分,这被称作包含关系。在这种情况
下,新用例不是初始用例的一个特殊例子,并且不能被初始用例所代替。在m伍中,包含
关系表示为虚线箭头加<<include> >字样,箭头指向被包含的用例。
包含关系使-个用例的功能可以在另一个用例中使用,如下所述。
(1)如果两个以上用例有大量一致的功能,则可以将这个功能分解到另 个用例中o 其
他用例可以和这个用例建立包含关系。
(2) 一个用例的功能太多时,可以用包含关系建模两个小用例。
3 扩展关系(Extend )
一个用例也可以被定义为基础用例的增量扩展,这称作扩展关系,扩展关系是把新的行
为插入到已有用例中的方法。同一个基础用例的几个扩展用例可以在一起应用。扩
展关系表示为虚线箭头加<<extend>>字样,箭头指向被扩展的用例(即基础用例。
基础用例提供了一组扩展点,在这些新的扩展点中可以添加新的行为,而扩展用例提供
了一组插入片段,这些片段能够被插入到基础用例的扩展点上。基础用例不必知道扩展用例
的任何细节,它仅为其提供扩展点。事实上,基础用例即使没有扩展用例也是完整的,这点
与包含关系有所不同。扩展关系为处理异常或构建灵活的系统框架提供了一种十分有效的方法。
4. 泛化关系(Generaliza苗。n)
一个用例可以被特别列举为一个或多个子用例,这被称作用例泛化。当父用例能够被使
用时,任何子用例也可以被使用。在UML中,用例泛化与其他泛化关系的表示法相同,用
一个三角箭头从子用例指向父用例。
posted @ 2013-11-10 20:13 Jacc.Kim 阅读(353) | 评论 (0)编辑 收藏

总体来说.UML由以下几个部分构成。
(1)视图。视图是表达系统的某方面特征的UML建模元素的子集,视图并不是图,
它是由一个或者多个图组成的对系统某个角度的抽象。在建立一个系统模型时,通过定义多
个反映系统不同方面的视图,才能对系统做出完整、精确的描述。
说明:一般情况下,视图又可以分为多种不同层次、不同功能用途的视图:
        a) 用例视图、b) 逻辑视图、c) 并发视图、d) 组件视图、e) 配置视图
(2) 图。视图由图组成.UML通常提供9种基本的图,把这几种基本图结合起来就可以
描述系统的所有视图。
说明:
        a) 在UML1.4时代,基本的9种图分别为:用例图、活动图、时序图、协作图、类图、状态图、对象图、组件图、部署图。
        b) 在UML2.0时代,还扩展了其他的几种图。如:交互图等等。
(3)模型元素。 UML中的模型元素包括事物和事物之间的联系。事物描述了一般的面向
对象的概念,如类、对象、接口、消息和组件等.事物之间的关系能够把事物联系在一起,
组成有意义的结构模型。常见的联系包括关联关系、依赖关系、泛化关系、实现关系和聚合
关系.同一个模型元素可以在几个不同的UML图中使用,不过同一个模型元素在任何图中
都保持相同的意义和符号。
说明:
        a) UML模型元素一般为:类、对象、活动、用例、协作、状态、接口、以及种事件关系等等。
(4)通用机制。UML提供的通用机制可以为模型元素提供额外的注释、信息或语义.这
些通用机制同时提供扩展机制,扩展机制允许用户对UML进行扩展,以便适应一个特定的
方法/过程、组织或用户。
说明:常用的通用机制为:a) 修饰、b) 注释、c) 规格说明、d) 通用划分、e) 扩展机制。
posted @ 2013-11-10 18:51 Jacc.Kim 阅读(299) | 评论 (0)编辑 收藏

看完以下概述,即可明白何为A星算法。

关于什么是A星算法,上网一查便知。在此只简要记录一些有关A星算法的要点
一:f、g、h值
f值:即:算法的估价值。是指对某一点的估价值。例如:要想从起点 S 到达终点 D,则中间可能会经过n个点,假如其中经过点:X ,则f(X),就是对点x的计算所得的估价值。当然,对于估价值,是越小越好。
g值: 即:从起点 S 到达点 X 实际所花的代价值。例如:以格子数为计量单位。则g值表示,从S到X所经过的格子数,即为实际所花费的代价值
h值: 即:从点 X 到达终点 D 可能要花费的值。也就是所谓的估计值,猜测值。这个值根据不同的应用,实现策略,将会有不同的结果。当然值越小是越好的。理由是:f(X) = g(X) + h(X) 。因为g(X)值是固定的,已知的。所以要想f(X)值越小,则只能h(X)的值越小。

二:节点与地图位置点
地图位置点不言而喻,是指地图上的某个具体点,因此,只要地图的划分方法确定,则地图位置点必然确定。
节点是A星算法中所需要依赖的数据信息存储相关的点。与地图位置点不同。节点中所存储的数据信息是灵活多变的。同时,同一个节点,可能对应于不同的地图位置点。一般情况下,节点中会存储地图位置点信息、当前节点的f、g、h值等等。
!!!note: 在A星算法中,节点只分为两类。一类是:待考察的节点。一类是:已考察的节点。
已考察节点是指:当所有与节点X相关连的节点的f、g、h值均已被赋值并且这些节点均已被添加到open表中时,则节点X就是已经被考察过了。

三:open表与closed表
open表中所存储的元素,全部都是需要进一步进行考察的节点。
closed表中所存储的元素,全部都是已经被考察过了的节点。

四:A星算法的实现步骤
    1) 令 P = 起始节点
    2) 把 f, g, h 值赋给 P
    3) 将 P 添加到 Open 表中。此时 P 是 Open 表中唯一的节点。
    4) 令 B = Open 表中的最佳节点。(提示:所谓最佳节点是指:该节点的 f 值最小)
        (1) 如果 B 是目标节点,则退出。此时已找到一条路径。
        (2) 如果 Open 表为空,则退出。此时没有找到路径。
    5) 令 C 等于一个与 B 相连的有效节点。
        (1) 把 f, g, h 的值赋给 C。
        (2) 检查 C 是在 Open 表里,还是在Closed表里。
            2.1: 若在 Closed 表里,则检查新路径是否比原先更好,若是则采用新路径。
            2.2: 否则把 C 添加到 Open 表里.
        (3) 对所有 B 的子孙节点重复步骤 5).
    6) 重复步骤 4).
posted @ 2013-06-23 12:37 Jacc.Kim 阅读(1284) | 评论 (0)编辑 收藏

转载自:http://blog.sina.com.cn/s/blog_6056c8830100zh1c.html

对于普通类型的对象来说,它们之间的复制是很简单的,例如:

int a=88;
int b=a;
而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量。下面看一个类对象拷贝的简单例子。

#include <iostream>
using namespace std;

class
CExample
{
private
:
 
int
a;
public
:
 CExample(
int
b)
 
{ a=b;}
 
void Show ()
 
{
cout
<<a<<
endl;
}

}
;

int
main()
{
 CExample A(
100
);
 CExample B
=
A;
 B.Show ();
 
return 0
;
}

运行程序,屏幕输出100。从以上代码的运行结果可以看出,系统为对象B分配了内存并完成了与对象A的复制过程。就类对象而言,相同类型的类对象是通过拷贝构造函数来完成整个复制过程的。下面举例说明拷贝构造函数的工作过程。

#include <iostream>
using namespace std;

class
CExample
{
private
:
int
a;
public
:
CExample(
int
b)
{ a=b;}

CExample(
const CExample& C)
{
a
=
C.a;
}

void Show ()
{
cout
<<a<<
endl;
}

}
;

int
main()
{
CExample A(
100
);
CExample B
=
A;
B.Show ();
return 0
;
}

CExample(const CExample& C)就是我们自定义的拷贝构造函数。可见,拷贝构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它的唯一的一个参数是本类型的一个引用变量,该参数是const类型,不可变的。例如:类X的拷贝构造函数的形式为X(X& x)。

当用一个已初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷贝构造函数就会被自动调用。也就是说,当类的对象需要拷贝时,拷贝构造函数将会被调用。以下情况都会调用拷贝构造函数:
一个对象以值传递的方式传入函数体
一个对象以值传递的方式从函数返回
一个对象需要通过另外一个对象进行初始化。

如果在类中没有显式地声明一个拷贝构造函数,那么,编译器将会自动生成一个默认的拷贝构造函数,该构造函数完成对象之间的位拷贝。位拷贝又称浅拷贝,后面将进行说明。

自定义拷贝构造函数是一种良好的编程风格,它可以阻止编译器形成默认的拷贝构造函数,提高源码效率。

浅拷贝和深拷贝

  在某些状况下,类内成员变量需要动态开辟堆内存,如果实行位拷贝,也就是把对象里的值完全复制给另一个对象,如A=B。这时,如果B中有一个成员变量指针已经申请了内存,那A中的那个成员变量也指向同一块内存。这就出现了问题:当B把内存释放了(如:析构),这时A内的指针就是野指针了,出现运行错误。

  深拷贝和浅拷贝可以简单理解为:如果一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝。下面举个深拷贝的例子。

#include <iostream>
using namespace std;
class CA
{
 public:
  CA(int b,char* cstr)
  {
   a=b;
   str=new char[b];
   strcpy(str,cstr);
  }
  CA(const CA& C)
  {
   a=C.a;
   str=new char[a]; //深拷贝
   if(str!=0)
    strcpy(str,C.str);
  }
  void Show()
  {
   cout<<str<<endl;
  }
  ~CA()
  {
   delete str;
  }
 private:
  int a;
  char *str;
};

int main()
{
 CA A(10,"Hello!");
 CA B=A;
 B.Show();
 return 0;
}

深拷贝和浅拷贝的定义可以简单理解成:如果一个类拥有资源(堆,或者是其它系统资源),当这个类的对象发生复制过程的时候,这个过程就可以叫做深拷贝,反之对象存在资源,但复制过程并未复制资源的情况视为浅拷贝。

浅拷贝资源后在释放资源的时候会产生资源归属不清的情况导致程序运行出错。

Test(Test &c_t)是自定义的拷贝构造函数,拷贝构造函数的名称必须与类名称一致,函数的形式参数是本类型的一个引用变量,且必须是引用。

当用一个已经初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷贝构造函数就会被自动调用,如果你没有自定义拷贝构造函数的时候,系统将会提供给一个默认的拷贝构造函数来完成这个过程,上面代码的复制核心语句就是通过Test(Test &c_t)拷贝构造函数内的p1=c_t.p1;语句完成的。
posted @ 2013-03-15 17:49 Jacc.Kim 阅读(311) | 评论 (0)编辑 收藏

许多时候,设计项目,日志是必不可少的。
比如:有时候你自己就是觉得自己设计的功能,肯定没有问题。可偏偏别人会说你设计的有问题。这时候,如果没有日志报告,则你只能调试跟代码。如此必须浪费许多时间。(这点本人也是感受很深啦)。相反,如果有了日志报告,则一看,就清楚是否真的有问题,以及问题出在哪里。。
于是,基于此体会,以下是本人设计的一个日志服务提供器。虽然,简单,但可以提供十分便捷的日志服务。(个人认为十分好用)

提示:具体文件,可从附件下载。
附件共4个文件:
LogUserConfig.h
LogConfig.h
LogProvider.h
LogProvider.cpp

附件:
LogProvider.zip
posted @ 2013-03-13 12:51 Jacc.Kim 阅读(926) | 评论 (2)编辑 收藏

    static std::wstring MBytesToWString(const char* lpcszString);
    
static std::string WStringToMBytes(const wchar_t* lpwcszWString);
    
static std::wstring UTF8ToWString(const char* lpcszString);
    
static std::string WStringToUTF8(const wchar_t* lpwcszWString);

std::wstring KKLogObject::MBytesToWString(const char* lpcszString)
{
    
int len = strlen(lpcszString);
    
int unicodeLen = ::MultiByteToWideChar(CP_ACP, 0, lpcszString, -1, NULL, 0);
    wchar_t
* pUnicode = new wchar_t[unicodeLen + 1];
    memset(pUnicode, 
0, (unicodeLen + 1* sizeof(wchar_t));
    ::MultiByteToWideChar(CP_ACP, 
0, lpcszString, -1, (LPWSTR)pUnicode, unicodeLen);
    wstring wString 
= (wchar_t*)pUnicode;
    delete [] pUnicode;
    
return wString;
}

std::
string KKLogObject::WStringToMBytes(const wchar_t* lpwcszWString)
{
    
char* pElementText;
    
int iTextLen;
    
// wide char to multi char
    iTextLen = ::WideCharToMultiByte(CP_ACP, 0, lpwcszWString, -1, NULL, 0, NULL, NULL);
    pElementText 
= new char[iTextLen + 1];
    memset((
void*)pElementText, 0, (iTextLen + 1* sizeof(char));
    ::WideCharToMultiByte(CP_ACP, 
0, lpwcszWString, 0, pElementText, iTextLen, NULL, NULL);
    std::
string strReturn(pElementText);
    delete [] pElementText;
    
return strReturn;
}

std::wstring KKLogObject::UTF8ToWString(
const char* lpcszString)
{
    
int len = strlen(lpcszString);
    
int unicodeLen = ::MultiByteToWideChar(CP_UTF8, 0, lpcszString, -1, NULL, 0);
    wchar_t
* pUnicode;
    pUnicode 
= new wchar_t[unicodeLen + 1];
    memset((
void*)pUnicode, 0, (unicodeLen + 1* sizeof(wchar_t));
    ::MultiByteToWideChar(CP_UTF8, 
0, lpcszString, -1, (LPWSTR)pUnicode, unicodeLen);
    wstring wstrReturn(pUnicode);
    delete [] pUnicode;
    
return wstrReturn;
}

std::
string KKLogObject::WStringToUTF8(const wchar_t* lpwcszWString)
{
    
char* pElementText;
    
int iTextLen = ::WideCharToMultiByte(CP_UTF8, 0, (LPWSTR)lpwcszWString, -1, NULL, 0, NULL, NULL);
    pElementText 
= new char[iTextLen + 1];
    memset((
void*)pElementText, 0, (iTextLen + 1* sizeof(char));
    ::WideCharToMultiByte(CP_UTF8, 
0, (LPWSTR)lpwcszWString, -1, pElementText, iTextLen, NULL, NULL);
    std::
string strReturn(pElementText);
    delete [] pElementText;
    
return strReturn;
}

posted @ 2013-03-13 11:32 Jacc.Kim 阅读(4736) | 评论 (0)编辑 收藏

仅列出标题
共14页: 1 2 3 4 5 6 7 8 9 Last