【问题标题】:How do you model this in a class diagram?您如何在类图中对此进行建模?
【发布时间】:2014-03-04 16:03:57
【问题描述】:

假设我有一个接口Interface 和一个实现Interface 的具体类ConcreteClass。现在考虑第三类MyClass。如果MyClass 的实例持有对ConcreteClass 的引用:

Interface ref = new ConcreteClass();

那么我应该在 UML 类图中将 MyClassInterfaceConcreteClass 关联吗?

谢谢

【问题讨论】:

    标签: oop inheritance uml class-diagram


    【解决方案1】:

    这取决于MyClass 的公共接口定义什么。

    如果公共接口使Interface 可用,那么您应该链接到图表上的那个。这将是通常的方法,因为Interface 是通用类型并指定合同。除非您有理由限制为 ConcreteClass,否则不要。

    如果公共接口使ConcreteClass 可用,那么您应该链接到图表上的那个。

    在运行时Interface 类型的变量实际上包含ConcreteClass 的实例这一事实是无关紧要的。该图表示关系。

    【讨论】:

    • 我不确定我是否明白你的意思。让我澄清一下:我的类没有实现接口。这些类的唯一关系是 ConcreteClass 实现了接口。
    • 而我的班级与接口有关联。
    【解决方案2】:

    仅使用界面。关键是您想要界面的行为。无论该接口的实现是什么,都无关紧要。 MyClass 与接口有关,与接口的实现无关。

    此原则称为按接口设计。在 nakosspy 给出的答案中,这是他的第一张照片。但最好将 ConcreteClass 的实现排除在外。在这个概念级别上,实施并不重要。如果有一个变量指向一个接口,那么对于受过教育的读者来说,是否也应该有一个具体的实现。

    如果您要引用 ConcreteClass,那么每次更改接口的实现时都必须更改图表。那不是你想要的。这是不好的编码实践和不好的 uml 实践。

    将 MyClass 和 Interface 之间关系的声明与 Interface 的实际实现分开是一种很好的编码习惯。举例:

    Interface ref = new ConcreteClass();
    

    不应在 MyClass 类中发生。

    你应该有这样的东西:

    class MyClass
      Interface ref;
    
      setRef(){
        ref = InterfaceImplementation();
      }
     }
    

    这样你就可以在不改变MyClass中的一行代码的情况下改变Interface的实现。虽然这在您编写一个类时可能看起来很麻烦,但当您管理数百个类时请考虑一下。

    【讨论】:

      【解决方案3】:

      所以:这取决于。

      MyClassConcreteClassInterface 关联同样合法。您不会在 UML 规范中找到问题的答案。为什么?因为答案在于您的问题领域,而不是建模语言。

      考虑两个人为的例子来说明这一点。

      示例 1:类之间的关联

      替补:

      • ICanBarkInterface
      • DogConcreteClass
      • TrainerMyClass

      假设我们要捕获的关联是Trains,即

      • 每个训练师训练多条狗
      • 每只狗最多由一名训练师训练

      在这种情况下,关联的存在是因为“Dogginess”,而不是“Barkiness”。所以它正确地存在于两个类之间。

      示例 2:类与接口之间的关联

      替补:

      • ILoggerInterface
      • FileLoggerConcreteClass
      • ApplicationMyClass

      在这种情况下,关系是关于“Logginess”,而不是“Fileness”。 Application 不应该关心接口是如何实现的;它只是想要一种记录消息的方法。所以类和接口之间存在关联

      总结 与关联几乎总是如此,解决问题的关键在于问题域本身,而不是建模语言。

      第一次。

      【讨论】:

        【解决方案4】:

        MyClassref 变量有两种呈现方式:您可以将其呈现为属性或关联。那么Interface 接口有两种替代符号:带有接口原型的方形或圆形。这使得 2*2=4 备选方案。

        1. ref 显示为关联并使用方形界面表示法。

        这里不能显示ref 取的初始值。那是因为您不能在关联中显示默认值。

        1. ref 显示为关联,但对接口使用圆形符号。

        与之前的替代方案一样,在这里你不能显示初始值。

        1. ref 显示为属性并使用方形界面表示法。

        在这里您可以显示默认值,因为您可以对属性执行此操作。 MyClassInterface 之间的关系以依赖关系的形式呈现。 MyClassConcreteClass 之间的依赖关系也是如此。 请注意,这种依赖关系(MyClass 依赖于 ConcreteClass)也可以在备选方案 1 和 2 中呈现,您可以添加一个从 MyClass 指向 ConcreteClass 的依赖关系箭头(虚线)。

        1. ref 显示为属性并使用圆形界面表示法。

        这里你可以再次显示默认值。

        如果我们还计算从呈现或不呈现依赖关系派生的替代方案,那么至少有 6 种方式来呈现相同的事物。现在的问题是选择哪个。 这取决于您想用图表可视化什么以及图表的目标对象。在这种情况下,如果 ref 的初始化是消息,那么您应该使用呈现它的替代方案。如果它不太重要,那么您可能更喜欢将 ref 显示为关联的图表。

        在一个真正的问题中,你有更多的元素,所以它有更多的选择。您始终可以决定展示什么以及如何展示。

        编辑:一些参考资料可帮助您理解接口实现的符号。

        wikipedia

        实现是类、接口、 将客户端元素与 供应商元素。类和类之间的实现关系 接口和组件与接口之间的显示类 实现接口提供的操作。

        您可以在uml-diagrams.org 找到一些快速参考示例和大量信息。

        这个出色的答案Explanation of the UML arrows 将帮助您提供更多示例。

        Here你还可以找到更多关于实现的信息。

        【讨论】:

        • 泛化连接是实线,根据UML标准。
        • 属性也将显示为关联。它们不是针对一项任务的两种解决方案。
        • "这里不能显示 ref 取的初始值。那是因为你不能在关联中显示默认值。"不。在这里你不能这样做,因为接口不能取任何值。从来没有。
        • 斜线表示依赖,而不是关联。与属性的关联将以虚线格式显示。嘿,你完全迷失在这个主题上,你为什么要解释得这么复杂?你也想让他迷路吗?
        • 1.这种关系是实现而不是概括。 2. 属性可以表现为属性或关联。 3.取初始值的不是接口,而是ref变量,它被定义为接口,但用默认值new ConcreteClass()初始化。 4.MyClassConcreteClass没有任何关联,但它依赖于它,因为'ref=new ConcreteClass()'代码。
        【解决方案5】:

        您可以将具体类的引用定义为:

        • 属性类型为 MyClass 中定义的接口(或 ConcreteClass),或
        • MyClass 和 Interface(或 ConcreteClass)之间的关联。

        没有更多可用的选项

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-01-11
          • 1970-01-01
          • 1970-01-01
          • 2010-09-30
          • 2011-01-05
          • 1970-01-01
          • 2016-07-10
          • 2015-08-15
          相关资源
          最近更新 更多