两个类之间的订阅关联关系表示当被关联类的对象中发生特定事件时,订阅类的对象将得到通知。订阅关联关系具有一项条件,它定义了使订阅者得到通知的事件。

解释 返回页首

在某些情况下,一个对象会依赖于在另一个对象中发生的特定事件。如果事件发生在边界对象或控制对象中,该对象就会直接将已发生的事件通知给其他对象。但是,如果事件发生在实体对象中,情况则稍有不同。如果没有接到特别的请求,实体对象就可能无法将任何事件通知给其他对象。

示例

假设已利用通过转帐从银行帐户提款的可能性建立了一个系统的模型。如果试图进行的提款操作使帐户中出现了负余额,就必须立即书写通知并将其发送给客户。建模为实体对象的帐户应该与客户是否得到通知无关。 而应当由边界对象来通知客户。

在上面的示例中,边界类必须反复地向实体对象提出问题“我等待的事件是否已经发生?”。为了使情况更加明确并将实施细节的确定推迟到设计阶段,可以使用一种特殊的关联关系来进行表示,它就是订阅关联关系。

订阅关联关系可以将任何类型的对象与实体对象关联关系在一起,它所表示的是,当实体对象中发生特定的事件时,关联关系对象将得到通知。我们建议,订阅关联关系只应该用来关联关系实体对象,因为正是实体对象的被动性导致了对订阅关联关系的需要。另一方面,接口对象和控制对象都可以启动通信。 因此,它们不需要被“订阅”,而可以通过其他方式履行它们的职责。

订阅关联关系将任何类型的对象与实体对象关联关系在一起。当被关联关系的实体对象中发生特定事件时,关联关系对象将得到通知。

注意,关联关系的方向说明了只有订阅对象才知道两个对象之间的关系。订阅说明全部包含在订阅对象中。而被关联关系的实体对象仍以通常的方式定义,它不必考虑其他对象是否对其活动感兴趣。这也意味着,您可以在模型中添加或删除订阅对象,而不会改变它所订阅的对象。

可以给订阅关联关系指定多重性,以指出关联关系对象可以同时与目标对象的多少个实例相关联。然后可以说明该关联关系的一项或多项条件,以指出在关联关系对象得到通知之前必须发生的事件。该事件可能是关联关系值或属性值所发生的变更,或者是某项操作的计算结果(的某一部分)。当发生该事件时,订阅对象将得到通知:已经发生了某个事件。注意,所传递的并不是有关事件结果的任何信息,而只是该事件已经发生这一事实。如果关联关系对象对发生该事件后的实体对象结果状态感兴趣,它就需要通过常规方式与该实体对象进行交互。这意味着它还将需要有一个到该对象的链接。

示例

在仓库处理系统中,必须对托盘进行抽样检查,以评测它们的平均使用寿命。因此,每当一个托盘在仓库中从一处到另一处移动了一百次,就要在特殊的测试站对该托盘进行检查。这种情况可利用从控制类 Pallet Spot Checker 到实体类 Pallet 的订阅关联关系来建模。Pallet 的每个实例都使用计数器属性来计算自己的移动次数。当移动次数达到一百次时,根据订阅关联关系的条件,Pallet Spot Checker 将得到通知。然后,Pallet Spot Checker 将创建一个特殊的 Task,它负载把托盘运送到测试站。Pallet Spot Checker 不需要任何到 Pallet 的链接,但必须有一个到 Task 的链接,以将其启动。

当托盘被移动了一百次后,Pallet Spot Checker 又将创建一个新的 Task。

订阅关联关系的条件应该用抽象的特征来表达,而不要用具体的属性或操作来表达。这样,关联关系对象就可独立于可能经常变更的被关联关系实体对象的内容。

订阅关联关系不会总是关联关系两个对象实例。从类到实例的订阅关联关系也是有效的,这是一种元关系。(这将在以下各小节中进行说明。)在另外一些情况(例如特定事件正好是类的实例化)下,订阅关联关系也会关联关系对象的类。

用法 返回页首

来自边界类的订阅关联关系 返回页首

有时,如果实体对象中发生了某个事件,边界类就必须得到通知。这将需要订阅关联关系

示例

以通过转帐从银行帐户提款为例。在此例中,控制对象 Transferal Handler 对实体对象 Account 执行操作。如果 Account 返回负数的余额,客户就将接收到一个由边界对象 Notice Writer 所编写的通知。因此,该对象有一个对 Account 的订阅关联关系。所规定的条件为余额小于零。只要发生该事件,就会通知 Notice Writer。这个特殊的订阅关联关系属于实例关联关系,因为,Notice Writer 的一个实例在不断地监视 Account 的实例中是否出现了透支。

如果除了余额不足外,客户不需要收到任何其他信息,那么这就足够了。但是,如果还应告诉客户余额有多么不足,Notice Writer 就必须对 Account 执行一项操作来了解确切的金额。为此,Notice Writer 必须有一个到 Account 的链接。

边界类 Notice Writer 订阅实体对象 Account 中余额低于特定标准这一事件。如果 Notice Writer 还需知道确切的负余额,它就必须有一个到 Account 的链接。

来自边界类的元关联关系的一个示例是:实体对象中的事件导致一个新窗口被显示给用户。这说明一个接口对象类订阅了实体对象的实例。

来自实体类的订阅关联关系 返回页首

示例

在处理网络的系统中,有一些充当网络节点的工作站,并且有使工作站互连的线路。每个工作站都通过多条线路连接到其他工作站。工作站的载量取决于正在进行传输的线路数量。如果 80% 以上的线路正在进行传输,工作站就就具有高载量;如果 20% 以下的线路正在进行传输,则为低载量,而这二者之间的所有载量均为中等载量。在我们的系统模型中有两个实体对象 Station 和 Line,其中 Station 具有对 Line 的订阅关联关系。该关联关系的条件是:当 Line 的状态(可能是被启用或被禁用)发生变更时,Station 就应得到通知。

此外,如果工作站的载量变为低,就将通知订阅 Station 的控制对象。下图继续使用该示例描述了这种情况。

某一 Line 实例的状态一旦发生变更,Station 实例将得到通知。

实体对象之间的订阅关联关系几乎总是实例关联关系,因为所涉及的对象通常都是已经存在的实例。但是,可能会出现这样的情况:当被关联关系的实体对象中发生指定的事件时,将创建订阅实体对象的一个实例。这种情况是从类到实例的关联关系,即元关联关系。也可以想象,特定实体对象的实例会希望知道何时创建另一个实体对象的新实例。

来自控制类的订阅关联关系 返回页首

示例

在上面的示例中,实体对象 Station 具有对实体对象 Line 的订阅关联关系。因此,每当 Line 实例的状态发生变更时,Station 都将得到通知。这样的状态变更将改变 Station 的载量。如果载量变为低,即正在进行通信的线路少于 20%,系统就必须在网络找到合适的新路径,以避开该工作站。当然,这并不是 Station 的任务,但它必须由控制对象 Station Supervisor(它具有对每个 Station 实例的订阅关联关系)来执行。

控制对象 Station Supervisor 订阅实体对象 Station,而实体对象 Station 则订阅实体对象 Line。

大部分情况下,来自控制对象的订阅关联关系是从类到实例的关联关系,或者相反,也就是说,它是元关联关系。 通常,要等到事件实际发生后,才会创建将用来处理实体对象中所发生事件的控制对象实例。但也可以想象,控制对象的实例会希望知道何时创建某个实体对象的新实例。因此,在少数几种情况下,这种订阅关联关系也可能是实例关联关系。

示例

在上面的示例中,从 Station Supervisor 到 Station 的订阅关联关系具有元关联关系的特征,即当 Station 的载量变为低时,得到通知的将是类 Station Supervisor。Station Supervisor 一旦收到该消息,就将创建用于处理该事件的实例。

© 1987 - 2001 Rational Software Corporation。版权所有。

分栏显示 Rational Unified Process

Rational Unified Process