views:

492

answers:

3

Hi,

Is there any difference in terms of implementation as how a composition design can be different from delegation. For example the code below seems to be doing delegation since the user cannot access the composed object (i.e "a") without using b. Hence, the user would need to invoke interfaces of class b and then "class b" invoke appropriate interfaces of "class a" making it delegation. Does this make sense ?

Class A {
friend class B;
private: 
A(){}; //dont want user to instantiate this class object since it wont sense without any context. Just like a room with no house.
void PrintStructure(){};
};

Class B{
public:
void PrintStructure(){a.PrintStructure();} //delegate

private:
A a; //composition
};
+2  A: 

There are a couple of differences I see:

  • Delegation involves re-exporting methods; in a composition relationship, the inner objects methods may be used only privately and not re-exposed.
  • Composition usually implies some kind of ownership semantics with implications for object lifecycle; the parent object "owns" the child and the child doesn't have much reason to exist on its own. Delegation does not have this implication.

The code you show uses delegation and association; the association may be composition, but it's difficult to tell without broader context or more information about the objects (it can be quite subtle and subjective when an association becomes a composition).

Michael E
Exporting methods isn't necessary for delegation. From Wikipedia: "In its original usage, delegation refers to one object relying upon another to provide a specified set of functionalities."
danben
+4  A: 

The term "composition" is usually used in terms of object modelling as an expression of a "has-a" relationship and is a form of association (another being aggregation). This is usually contrasted with "inheritance" ("is-a" relationship). So:

What's the difference between composition and aggregation? Composition implies that the child cannot exist without the context of the parent.

For example, a House has one or more Rooms. That's a composition relationship. Delete the house and the rooms also cease to exist. A House also has a number of occupants, being instances of Person. That's an aggregation relationship because those people exist outside of the context of that house.

Delegation is nothing more than an implementation detail. A class has a public interface that describes its state and behaviour. How that is implemented is irrelevant. It could delegate to other objects or not.

You'll note that both A and B from your example have the same external interface. It's more common to do something like this:

// this represents an interface
class A {
public:
  virtual void printStructure() = 0;
}

with concrete classes:

class ConcreteA : A {
public:
  virtual void printStructure() { ... }
}

and

class DelegateA : A {
public:
  DelegateA(A& a) { this.a = a; }
  virtual void printStructure() { a.printStructure(); }
private:
  A a;
}

Excuse my probably C++ syntax errors. I'm a little rusty.

cletus
If composition implies that child cannot exist without the context of the parent then should the user never be allowed to create an object of the composed class ? For e.g my refined e.g would be class A { friend Class B; private: A(){}; void PrintStructure(){}; }; Class B{ public: void PrintStructure(){a.PrintStructure();} //delegate private: A a; //composition }; Now class B has class A. A User must use only class B interfaces to change class A behaviour and class B should delegate such tasks to class A functions. Is this design good ?
Frank Q.
@Frank: Friend classes are one way to implement this kind of relationship. They're not I favour though. A more elegant solution is to have the constructor for Room to require an instance of House, which then becomes its "parent".
cletus
How would you code something like that in my example? Moreover I dont want the user to be able to instantiate an object of A since it would not make sense to do any operations on A without the context of B.
Frank Q.
@Frank: my version of A has a pure virtual function. It can't be instantiated.
cletus
A: 

Composition is about the relationships between objects.

Delegation is about passing work from one object to another.

These are actually different (but sometimes related) concerns.

What you've got is B composed of A (B refers to A). B also delegates its one method to A.

But since B's use of A is private (fully encapsulated within B's black box), I wouldn't call B's use of A "composition". I would use "composition" only if class A could be accessed from B. What's important here is if B's logical model "has-a" A.

In your case, B is implemented in terms of A. Since this is an implementation concern it can be considered as not part of B's logical model. That is, you can talk intelligently about B without talking or caring about A.

That all said, this stuff is really only important to PHB's and UML modeling tools. Or perhaps if you are studying Design Patterns. I wouldn't get too hung up on it.

[PHB => Pointy Haired Boss]

rickmode
Does that mean in composition the composed object (in this case "a") has to be made public ? This way the user would access a using b e.g B b; b.a.PrintStructure(); //assuming member function is public.
Frank Q.
There is no absolute right or wrong here. What matters is the intent of the classes. You should not make the "a" member of class B public just because of some notion of "composition". Rather consider if "a" is important to the code using an instance of class B. If the code using B needs to get to "a", then there should be a way (method) on B to access it. In your example, "a" is private, so its existence and use in B is entirely hidden from code using class B. This is generally a good thing.More:http://en.wikipedia.org/wiki/Information_hiding http://en.wikipedia.org/wiki/Object_composition
rickmode
@rickmode: Thanks, I started a diffrent thread if returning a reference to private member in composition breaks OOP. In my case B has to have A and yet user needs to set some propertoes of A which would require him/her some way to get to A. I dont want to use delegation either which would require me to expose methods in B for every method in A.
Frank Q.