16

i can't seem to understand completely the difference between aggregation and composition in a code.

Client <.>---->BankAccount

(this is supposed to be Client - BankAccount composition class diagram).

So in this example, Client has a bank account, so this means, when a client object dies, his bank account object dies too. Does this mean, that we have to have a BankAccount object within Client class ?

Class Client
{

    BankAccount acc = new BankAccount();

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

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

}

So, is this composition in code ? What would aggregation look like in this example? Sorry for the newbie question, please correct me if the code was wrong. Thanks in advance.

Hamlet Hakobyan
  • 32,965
  • 6
  • 52
  • 68
Mefhisto1
  • 2,188
  • 7
  • 34
  • 73

4 Answers4

15

Yes, What you do is call composition, if you want to do aggregation you to it like this:

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();
    }

}

Aggregation:

If inheritance gives us 'is-a' and composition gives us 'part-of', we could argue that aggregation gives us a 'has-a' relationship. Within aggregation, the lifetime of the part is not managed by the whole. To make this clearer, we need an example. For the past 12+ months I have been involved with the implementation of a CRM system, so I am going to use part of this as an example.

The CRM system has a database of customers and a separate database that holds all addresses within a geographic area. Aggregation would make sense in this situation, as a Customer 'has-a' Address. It wouldn't make sense to say that an Address is 'part-of' the Customer, because it isn't. Consider it this way, if the customer ceases to exist, does the address? I would argue that it does not cease to exist. Aggregation is shown on a UML diagram as an unfilled diamond.

As I said at the beginning of the answer, this is my take on composition and aggregation. Making the decision on whether to use composition or aggregation should not be a tricky. When object modelling, it should be a matter of saying is this 'part-of' or does it 'have-a'?

One Man Crew
  • 9,420
  • 2
  • 42
  • 51
  • I'm a little confused. Given this sentence : "Within aggregation, the lifetime of the part is not managed by the whole". Suppose a Runtime code makes a call like this: new Client( new BankAccount()).Isn't the lifetime of the part managed by the Client since the BankAccount was passed as a parameter in constructor and so would only exists during Client's lifetime ? – Bruno Barros Mar 02 '17 at 13:51
8

Your client-BankAccount code is a composition relationship

Your code satisfies all the properties of composition

->the lifetime of the part classifier(BankAccount) is dependent on the lifetime of the whole classifier(Client).

->data usually flows in only one direction (that is, from the whole classifier(Client) to the part classifier(BankAccount).


Aggregation can be represented by passing BankAccount to client as an argument to a method

So,this code is Aggregation

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

As you can see it satisfies all the properties of Aggregation

->it can exist independently of client

->Data flows from the whole classifier(client) to the part(BankAccount)

Anirudha
  • 32,393
  • 7
  • 68
  • 89
  • The confusion I'm having is: if we call updateAccount(new BanckAccount()) at runtime, the bankAccount would still only exists in the context of the whole (Client) because it wouldn't be referenced in no other place but in the whole context. – Bruno Barros Mar 02 '17 at 13:59
  • @BrunoBarros it depends how you call it. Most of the time you will be calling the method with already created object i.e `updateAccount(my_bank_account);` which will in turn satisfy the aggregation relationship. – Anirudha Mar 02 '17 at 18:37
3

This explanation from IBM is helpful to me:

For example, we can think of Car as a whole entity and Car Wheel as part of the overall Car. The wheel can be created weeks ahead of time, and it can sit in a warehouse before being placed on a car during assembly. In this example, the Wheel class's instance clearly lives independently of the Car class's instance. However, there are times when the part class's lifecycle is not independent from that of the whole class — this is called composition aggregation. Consider, for example, the relationship of a company to its departments. Both Company and Departments are modeled as classes, and a department cannot exist before a company exists. Here the Department class's instance is dependent upon the existence of the Company class's instance.

So to me, the creator/destroyer life cycle (new, release) for a composition goes inside an instance; an aggregation must have the option instead to addObject and the method simply save the object id as an attribute of itself. So in the above Client and Bank Account example, it's really up to the business to determine if an Account can exist even if the Client record is destroyed (orphaned accounts) If it is aggegator, you would have Client methods:

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

and the close account method would be part of the BankAccount object instance, since it can exist independently from the Client.

versus the composition method which requres the Client to exist, and if the Client ceases to exist, all the accounts belonging to that account owner are deleted. Therefore, you would ask the Client object to create you an account:

Class Client {
- (BankAccount *) openAccount;
- (BOOL) closeAccount:(BankAccount *)acc;
}
PapaSmurf
  • 2,345
  • 1
  • 20
  • 10
1

Yes, you are right. This is a simple composition.

For an aggregation, your Client class should keep reference for BankAccount class, but should not control it's object lifetime.

class Client
{
     private readonly BankAccount _account;

     public Client(BankAccount account)
     {
         _account = account;
     }

     //...
}

After Client object will be destroyed, BankAccount object used within can be assigned for an another Client.

Dzmitry Martavoi
  • 6,867
  • 6
  • 38
  • 59
  • Thanks for the answer, but i have a follow up question: private readonly BankAccount _account; public Client(BankAccount account) { _account = account; } Here in the Client Constructor, does that initiate a new BankAccount object, and then you assign our readonly variable _account to reference that object, referenced by account variable? – Mefhisto1 Jan 27 '13 at 15:38
  • You should pass account object contained in, for example, independent collection within specified Bank object. The main idea I that you can`t control BanckAccount object lifetime (as Composition relation do), but you reference to it. If you simply write var client = new Client(new BankAccount) - it will not be aggregation(coz account object will be destroyed at the same time as the client object). You can make private constructor for BankAccount class, and create new objects using AccountFactory that contains all the accounts for the specified Bank. – Dzmitry Martavoi Jan 27 '13 at 17:24