当前位置: 首页 > 知识库问答 >
问题:

差异聚合,相识和组成(由四人帮使用)

钱元徽
2023-03-14

我一直在读Erich Gamma等人的《设计模式:可重用面向对象软件的元素》,并且读到了解释聚集和相识的部分(第22-23页)。以下是摘录(抱歉,如果太长,但我认为解释这个问题很重要):

考虑对象聚合和相识之间的区别,以及它们在编译和运行时表现出的不同。聚合意味着一个对象拥有另一个对象或对另一个对象负责。通常我们说一个对象具有或是另一个对象的一部分。聚合意味着聚合对象和它的所有者有相同的生命周期。

相识意味着一个对象只知道另一个对象。有时熟人被称为“关联”或“使用”关系。相熟的对象可能会请求彼此的操作,但它们不相互负责。相识是一种比聚合更弱的关系,并且表明对象之间的耦合要松散得多。

[…]

归根结底,相识和聚合更多地是由意图而不是明确的语言机制决定的。在编译时结构中可能很难看到这种区别,但它很重要。聚合关系往往比熟人更少,更持久。相比之下,熟人更频繁地制作和重制,有时只在手术期间存在。熟人也更加动态,这使得它们在源代码中更难辨别。

令我困惑的是,这里描述的聚合具有组合的特征:一个组合对象管理其他对象,并且它们的生存期是绑定的。

另一方面,在该摘录中定义的熟人具有聚合的特征:聚合对象知道其他对象,但它不管理它们。

也是部分

有时熟人被称为“交往”或“使用”关系。

令人困惑,因为我认为聚合和组合都是关联的形式,而聚合是耦合较少的形式。

会不会是作者把聚集称为相识,把组合称为聚集,或者我遗漏了什么?

共有3个答案

谷梁凌
2023-03-14

会不会是作者把聚集称为相识,把组合称为聚集,或者我遗漏了什么?

OMT于1991年出版,UML于1997年出版,《设计模式》一书于1994年出版。因此,作者使用OMT聚合来指代UML复合聚合(AKA组合)。

以下是UML定义:

>

  • 聚合(又名拥有关系)是一种部分-整体关系,意思是没有部分,整体就不能存在(不是反过来)。部分是整体的一个基本属性。例如,一辆车(整体)和它的引擎(部分)是聚合的,因为一辆车需要它的引擎存在。

    另一方面,交往(即熟人关系或使用关系)并不是一种整体关系。一个对象是另一个对象的偶然属性。E、 汽车和它的主人是联系在一起的,因为汽车不需要它的主人存在。

    注意。-聚合可以细分为两类:共享聚合,其中部分可以在没有整体的情况下存在,以及复合聚合(AKA组合,或者我喜欢称之为唯一聚合),其中部分不能在没有整体的情况下存在。

    工具书类

    Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides的《设计模式:可重用面向对象软件的元素》。

    考虑对象聚合和相识之间的区别,以及它们在编译和运行时表现出的不同。聚合意味着一个对象拥有另一个对象或对另一个对象负责。通常我们说一个对象具有或是另一个对象的一部分。聚合意味着聚合对象和它的所有者有相同的生命周期。

    相识意味着一个对象只知道另一个对象。有时熟人被称为“关联”或“使用”关系。相熟的对象可能会请求彼此的操作,但它们不相互负责。相识是一种比聚合更弱的关系,并且表明对象之间的耦合要松散得多。

    Peter Grogono和Markku Sakkinen的《复制与比较:问题与解决方案》。

    我们区分物体的基本属性和偶然属性。{脚注:这种区别大致基于亚里士多德的范畴。基本属性无疑是对象的一部分;意外属性是另一个对象,它以某种方式与相关对象相关,但不是它的一部分。例如,如果所讨论的对象是类 Car 的实例,我们会认为属性引擎是必不可少的,但基本值 distanceTravelled 和引用所有者是偶然的。“偶然”和“必要”之间的区别与“参考”和“遏制”之间的区别是正交的。该模型允许所有四种可能性。当属性由引用表示时,它是引用对象本身,而不是引用,这是偶然属性或基本属性。

    偶然属性旨在作为联想的概括。关联是“对等体之间的结构关系”,其中“对等体”是相同概念级别的类。关联是一种偶然属性,但不是唯一的一种。关联通常被实现为对其他成熟对象的引用,尽管已经提出了更精细的实现。但是对象也可以包含计数器、标志、描述符和应用软件所需的其他属性,但在概念上不是对象的一部分。

    本质的和偶然的区别并不总是明显的。根据经验,如果销毁一个对象在逻辑上不需要销毁另一个对象,则两个对象之间的关系是关联(因此是偶然的),否则一个对象是另一个对象的属性。类似地,如果从对象中移除属性不会破坏对象的基本完整性,则属性是偶然的。

  • 令狐珂
    2023-03-14

    组合:当一个类由另一个类的数据成员组成时。

    Class A
    {
       B ObjB;
    }
    

    聚合:当一个类的方法在其作用域内创建其他类的对象时

    void A::methA()
    {
       B* ObjB= new B();
       delete ObjB;
    }
    

    熟识/使用:当一个类的方法接受对另一个类的对象作为参数的引用时

    void A:methA (B& objB) 
    {
    
    }
    
    贺卜霸
    2023-03-14

    我学到的是你写的:

    是作者们把聚合称为熟人,把合成称为聚合,还是我遗漏了什么?

    对我的理解是:

    > < li>

    开始时,当您进行(粗略)分析时,请从关联的角度进行思考。在这个阶段通常就足够了。

    稍后,当您描述(详细)设计时,您需要决定对象的所有权、它们的生命周期、实例化、清理等。

    更详细地指定关联-将其分为两组:

    • 聚合(对象可能独立存在的更自由的关系)和
    • 组合(一个对象负责另一个对象的生命周期的更紧密的关系)。

    但是,不取决于您使用的术语(四人帮之一或我在这里描述的UML定义),所有术语都表示整个对象之间的关系,而不仅仅是对象的单个方法使用局部变量(或参数,这只是局部变量的特殊类型)与另一个对象。

    class Car {
        // There is an association between Car and RegistrationPlate.
        // This association is either composition or aggregation.
        // The type of association is *not* deferrable from the syntax here.
        // This is purely the design decision and depends on many things,
        // both technical and business logic.
        // In some countries the registration plates are movable among cars,
        // in others they are cancelled when you scrap the car.
        RegistrationPlate registrationPlate;
    
        // Technically, there is an association between Car and List
        // but we rarely call it like that. Instead we say
        // "there is one to many association between Car and Tyre"
        // and the List is viewed just as an implementation detail.
        List<Tyre> tyres;
    
        // There is neither association nor composition nor aggregation 
        // between Car and Engine and Fuel
        // but instead  Car <<uses>> Engine   and   Car <<uses>> Fuel.
        void doSomething(Fuel fuel) {
            Engine engine = new Engine();
            // (method parameter fuel is just a special case of a local method variable)
            ...
        }
    }
    

    在代码中,聚合和组合乍一看可能是一样的,尤其是在带有垃圾收集器的语言中(如Java、静态编程语言或C#),程序员不必如此关心清理[注1]。然而,不同之处在于关联对象生命周期的责任:

    • 在组合的情况下,“容器”对象必须负责其组件的所有必要清理
    • 在聚合的情况下,情况要复杂得多,因为聚合对象有自己的生命周期,您必须非常小心地正确实现清理

    [注1]即使在使用垃圾收集器的语言中,您也必须经常考虑清理,例如关闭打开的连接、释放文件句柄,以及有效地处理丢失对对象的引用,以便它们符合GC——不要忘记收集中未使用的对象、使用弱引用或其他技术。这超出了这个问题的范围。

     类似资料:
    • 任何人都可以给出代码示例来显示聚合和组合之间的区别。我已经阅读了这篇文章,但不明白它们在代码上有何不同。 请通过代码显示差异。

    • 我知道聚合和组合之间的概念差异。有人能用实例告诉我它们之间在Java中的实现区别吗?

    • 问题内容: 我想知道如何在python中以 UML术语 实现组合和聚合。 如果我了解: 聚合: class B: pass class A(object): def init(self): self.B = B 组成: 在其他语言中,我将其实现为指向B的指针。我猜这是python中的指针。 这样对吗? 问题答案: 如果我正确理解,聚合与组合是关于对象对其成员的职责(例如,如果删除实例,是否还要删除

    • 问题内容: 我要分析一组客户。我对客户增长感兴趣,例如: 自上周以来增加了43位新客户(+ 32%) 自去年以来+12650(+ 1140%)新客户 该怎么办: 获得本周创造的客户 获取上周创建的客户 数他们 计算差异(百分比) 因此,首先,我将创建一个直方图,按周对客户进行分类: 这例如导致 然后,我只需要获取最后两个条目并计算差异,然后将其分配给buckets集合之外的字段。在Elastics

    • 我想对3条路由使用Apache Camel并行组播,聚合(并等待)其中的2条路由,而让第3条路由自行进行(第3条路由不应阻塞前两条路由)。我还需要在“所有”情况下处理这两个,这意味着如果其中一个失败(例如在处理过程中抛出异常),也应该对其进行聚合。 根据我从Camel文档中了解到的情况,只要不指定StoponException,该行为就应该是“默认的”。但发生的情况是exchange异常永远不会到

    • 如何识别代码中的组合和聚合?特别是在为现有代码绘制类图时? 我知道组成是“HAS-a”关系,聚合是“PART OF”关系。我知道,在组合子类中,实例将随类一起销毁,而在聚合中则不会。 下面是一个 C/CLI 代码 报警 报警.cpp 据我所知,警报和通知之间的联系是组合,因为没有就没有。我说的对吗?如果我是对的,我怎样才能使这段代码在两个类之间具有聚合关系?请问那里的代码示例? 请帮忙。