如何在UML对象和序列图中分别显示同一对象的引用类型和对象类型

如何在UML对象和序列图中分别显示同一对象的引用类型和对象类型,uml,class-diagram,sequence-diagram,ooad,object-diagram,Uml,Class Diagram,Sequence Diagram,Ooad,Object Diagram,该图显示了示例类图以及序列图中这些类的对象的用法 在上图中,myCar实例可以通过ShowroomItem的引用或接口车辆的引用来引用。因此,客户机驱动程序/销售工程师将获得功能访问权限 我同意在实现阶段(例如Java),这里不需要类型标识,我们将把myCar视为自己使用的基类型(任何一个接口)的实例 但在序列图中,(为了清楚起见),我无法指出我的汽车驾驶员的参考应为车辆,销售工程师的参考应为展厅项目 我在UML2.0书籍中搜索,没有找到合适的符号。根据目前的理解,我可以将其显示为“myCar:

该图显示了示例类图以及序列图中这些类的对象的用法

在上图中,myCar实例可以通过ShowroomItem的引用或接口车辆的引用来引用。因此,客户机驱动程序/销售工程师将获得功能访问权限

我同意在实现阶段(例如Java),这里不需要类型标识,我们将把myCar视为自己使用的基类型(任何一个接口)的实例

但在序列图中,(为了清楚起见),我无法指出我的汽车驾驶员的参考应为车辆,销售工程师的参考应为展厅项目

我在UML2.0书籍中搜索,没有找到合适的符号。根据目前的理解,我可以将其显示为“myCar:Vehicle”或“myCar:ShowroomItem”,但这并不表示其Car对象称为接口。此快捷命令并不强制要求playMusic在被称为Vehcile时不能工作

有什么符号来表示这种细节吗

由于我对所提供的任何答案都不满意,因此我尝试添加以下内容,以使问题更加清楚,解决答案中提出的一些异议,并提出解决方案供专家审查。

看这些评论,我觉得要么人们没有理解核心问题,要么我没有突出核心问题。首先,让我演示代码不会中断。下面的代码允许SalesEngineer使用sell()和buy()功能访问抽象,而驱动程序只使用start()和stop()功能访问抽象[以这种方式设计]。这是接口的一个强大功能,可以向不同的客户机发布不同的抽象。Java集合使用相同的多个基本类型,即TreeSet中的Object和Compariable,一个用于equals(),另一个用于实体上的compare()

package com.se.stackoverflow;

interface Vehicle {
    abstract void start();
    abstract void stop();
}

interface ShowroomItem {
    abstract void buy();
    abstract void sell();
}

class Car implements ShowroomItem, Vehicle {
    // **Car IS-A Vehicle and ShowroomItem BY-DEFINITION**
    // **and as per SOLID principle interface segregation**

    public void start() { System.out.println("Started");}
    public void stop() { System.out.println("Stopped");}
    public void sell() { System.out.println("Sold");}
    public void buy() { System.out.println("Baught");}
}

class SalesEngineer {
    private ShowroomItem item = null;
    public SalesEngineer(ShowroomItem item) { this.item = item;}
    public void doTransaction() {item.buy(); item.sell();}
}

class Driver {
    private Vehicle veh = null;
    public Driver(Vehicle veh) {this.veh = veh;}
    public boolean testDrive() {veh.start(); veh.stop(); return true;}
}

public class ShowroomOwner {
    public void makeDeal(Car carForDeal) {
        Driver driver = new Driver(carForDeal);
        SalesEngineer engineer = new SalesEngineer(carForDeal);
        if (driver.testDrive()) {
            engineer.doTransaction();
        }
    }

    public static void main(String[] args) {
        // simulates client as ShowroomOwner to save space
        new ShowroomOwner().makeDeal(new Car());
    }
}
在参考Jim Arlow的“UML2和统一过程”之后,我发现我们可以在序列图中显示生命线上的变化状态。我觉得我们可以用类似的符号来表示变化的对象类型[我在任何地方都没有看到UML中记录了这一点,但这是我对UML小组的建议]

e、 g.此处myCar是其类别Car的对象(对象类别永远不能更改),但其参考类型根据左侧的不同而不同,如展厅项目或车辆

可能下面的序列图可以显示出来。[示例类仅用于突出显示自动类型的铸造效果]


由于
汽车
ShowRoomItem
继承(根据您的UML),因此它还将具有
sell()
操作,并且
SalesEngineer
可以使用它


我觉得你的模型很奇怪。一辆有
sell()
操作的车肯定是我不会买的。换言之:你的课程模型是坏的。

首先,你的课程图是错误的,一辆车不是一个展厅项目,一辆车在出海/购买前后都是一样的,在你的情况下,由于它是出海/购买,汽车将不得不停下来(可能是暂时的)作为一个展厅项目。事实上,它不是一种类型,而是一种状态,但对我来说,将该状态作为汽车的属性也是一个错误的选择

第二,司机或销售工程师访问的实际情况是一辆汽车,汽车不关心谁在使用它,当这个人是销售工程师时,收音机不会消失,因此如果有足够的先决条件,汽车总是接受播放收音机(电池通电,可能钥匙打开等)

事实上,根据人是谁而定的限制不能在汽车的层面上进行,否则这是不真实的,完全是人为的,而是在人/角色的层面上

在UML中,对于这种限制,您可以使用约束。

UML符号问题 您需要选择要为序列图的每条生命线显示的类型,因为UML只允许一个生命线。由于
myCar
是一款实现
Vehicle
ShowroomItem
Car
,因此您可以选择这三种类型中的任何一种

一旦选择了类型,UML就无法在同一个图中提供关于该类型的备用视图。您可以使用
myCar
作为
Car
显示场景。但是其他生命线必须符合他们知道的接口(前提是没有其他使用依赖项允许他们访问完整的汽车),并且由您来确保一致性。这可能容易出错,正如您在
playMusic()
中所演示的那样

您可以通过图表中的一个或几个注释来解决您的问题,以纯文本形式提醒读者与接口相关的约束。但是更好的方法是保持它的简单性,并在两个单独的图表中显示
SalesEngineer
Car
之间以及
Driver
Car
之间的交互。这更接近您设计的实际情况,并促进声音关注点的分离

面向对象设计问题 并且已经指出了你设计中的弱点。我完全同意他们的看法。实际上,
汽车
就是
汽车
。但是
汽车
不是
展厅项目
:汽车可以临时扮演展厅项目的角色。或者,一个展厅项目可能在给定时间对应于一辆特定的汽车

如果汽车不是展厅项目,它既不应从此类继承,也不应实现此类接口。因此,请选择,例如:

  • SalesEngineer
    交易
    ShowroomItem
  • CarForSale
    实现
    ShowroomItem
  • CarForSale
    与一辆
    Car
  • 驾驶员
    驾驶
    车辆