【问题标题】:composition and aggregation example with UML class diagram使用 UML 类图的组合和聚合示例
【发布时间】:2013-01-10 23:58:49
【问题描述】:

我似乎无法完全理解代码中聚合和组合之间的区别。

客户<.>---->银行账户

(这应该是 Client - BankAccount 组合类图)。

所以在这个例子中,客户有一个银行账户,所以这意味着,当一个客户对象死亡时,他的银行账户对象也会死亡。这是否意味着我们必须在 Client 类中有一个 BankAccount 对象?

Class Client
{

    BankAccount acc = new BankAccount();

    public void addMoneyToBankAccount(decimal amount)
    {         
        acc.AddMoney(amount);
    }

    public decimal CheckBalance()
    {
        return acc.CheckAccountBalance();
    }

}

那么,这是代码中的组合吗?在这个例子中聚合会是什么样子? 抱歉新手问题,如果代码错误,请纠正我。提前致谢。

【问题讨论】:

    标签: c# uml class-diagram


    【解决方案1】:

    是的,你做的是调用组合,如果你想像这样聚合你:

    Class Client
    {
    
        BankAccount acc;
    
        public Client(BankAccount p_acc)
        {
          acc=p_acc;
        }
    
        public void addMoneyToBankAccount(decimal amount)
        {         
            acc.AddMoney(amount);
        }
    
        public decimal CheckBalance()
        {
            return acc.CheckAccountBalance();
        }
    
    }
    

    聚合

    如果继承给了我们“is-a”,而组合给了我们“part-of”,我们可以说聚合给了我们“has-a”关系。在聚合中,部分的生命周期不由整体管理。为了更清楚地说明这一点,我们需要一个例子。在过去的 12 个月里,我一直在参与 CRM 系统的实施,因此我将使用其中的一部分作为示例。

    CRM 系统有一个客户数据库和一个单独的数据库,其中包含一个地理区域内的所有地址。在这种情况下,聚合是有意义的,因为客户“拥有”地址。说地址是客户的“一部分”是没有意义的,因为它不是。这样考虑,如果客户不复存在,地址呢?我认为它不会不复存在。聚合在 UML 图上显示为未填充的菱形。

    正如我在答案开头所说,这是我对组合和聚合的看法。决定是使用组合还是聚合应该不是一件棘手的事情。在对象建模时,应该说这是“部分”还是“有”?

    【讨论】:

    • 我有点困惑。鉴于这句话:“在聚合中,部分的生命周期不由整体管理”。假设运行时代码进行如下调用:new Client(new BankAccount())。由于 BankAccount 是作为参数在构造函数中传递的,因此该部分的生命周期不是由 Client 管理的,因此仅在 Client 的生命周期中存在?
    【解决方案2】:

    您的客户-BankAccount 代码是composition 关系

    您的代码满足组合的所有属性

    ->部分分类器(BankAccount)的生命周期取决于整个分类器(Client)的生命周期。

    ->数据通常只流向一个方向(即从整个分类器(Client)流向部分分类器(BankAccount)。


    可以通过将 BankAccount 作为方法的参数传递给客户端来表示聚合

    所以,这段代码是聚合

    class client
    {
        public bool updateAccount(BankAccount ba){....}
    }
    

    如您所见,它满足聚合的所有属性

    ->它可以独立于client而存在

    ->数据从整个分类器(client)流向部分(BankAccount

    【讨论】:

    • 我的困惑是:如果我们在运行时调用 updateAccount(new BanckAccount()),bankAccount 仍然只存在于整个(客户端)的上下文中,因为它不会仅在整个上下文中引用。
    • @BrunoBarros 这取决于你如何称呼它。大多数时候,您将使用已创建的对象调用该方法,即updateAccount(my_bank_account);,这反过来又会满足聚合关系。
    【解决方案3】:

    这个解释from IBM对我有帮助:

    例如,我们可以将 Car 视为一个整体实体,而将 Car Wheel 视为整个 Car 的一部分。轮子可以提前几周制造出来,它可以放在仓库里,然后在组装过程中放在汽车上。在这个例子中,Wheel 类的实例显然独立于 Car 类的实例。但是,有时部分类的生命周期并不独立于整个类的生命周期——这称为组合聚合。例如,考虑一家公司与其部门的关系。公司和部门都被建模为类,部门不能在公司存在之前存在。这里 Department 类的实例依赖于 Company 类的实例的存在。

    所以对我来说,组合的创建者/销毁者生命周期(新的、发布的)进入实例内部;聚合必须具有选项而不是 addObject 并且该方法只需将对象 ID 保存为自身的属性。因此,在上面的客户和银行帐户示例中,即使客户记录被破坏(孤立帐户),帐户是否可以存在也完全取决于企业,如果它是聚合器,您将拥有客户方法:

    Class Client {
    - (void) addToAccount:(BankAccount *)acc;
    - (void) removeFromAccount:(BankAccount *)acc;
    }
    

    关闭账户方法将是 BankAccount 对象实例的一部分,因为它可以独立于客户端存在。

    与要求客户存在的组合方法相比,如果客户不存在,则属于该帐户所有者的所有帐户都将被删除。因此,您会要求 Client 对象为您创建一个帐户:

    Class Client {
    - (BankAccount *) openAccount;
    - (BOOL) closeAccount:(BankAccount *)acc;
    }
    

    【讨论】:

      【解决方案4】:

      是的,你是对的。这是一个简单的作曲

      对于聚合,您的 Client 类应保留 BankAccount 类的引用,但不应控制其对象生命周期。

      class Client
      {
           private readonly BankAccount _account;
      
           public Client(BankAccount account)
           {
               _account = account;
           }
      
           //...
      }
      

      Client 对象销毁后,其中使用的 BankAccount 对象可以分配给另一个 Client。

      【讨论】:

      • 感谢您的回答,但我有一个后续问题:private readonly BankAccount _account; public Client(BankAccount account) { _account = account;在客户端构造函数中,这是否会启动一个新的 BankAccount 对象,然后您分配我们的只读变量 _account 来引用该对象,由 account 变量引用?
      • 您应该传递包含在例如指定银行对象中的独立集合中的帐户对象。我的主要思想是你不能控制 BanckAccount 对象的生命周期(就像组合关系一样),但是你引用它。如果您简单地编写 var client = new Client(new BankAccount) - 它不会是聚合(因为帐户对象将与客户端对象同时被销毁)。您可以为 BankAccount 类创建私有构造函数,并使用 AccountFactory 创建包含指定银行的所有帐户的新对象。
      猜你喜欢
      • 2021-12-16
      • 2011-05-03
      • 2013-05-14
      • 2018-06-27
      • 1970-01-01
      • 2016-07-22
      • 2014-02-08
      • 2011-07-14
      • 2011-12-26
      相关资源
      最近更新 更多