I am facing a continuing problem distinguishing delegation, composition and aggregation from each other, and identifying the cases where it's the best to use one over the other.
I have consulted a Java OO Analysis and Design book, but my confusion still remains. The main explanation is this:
Delegation: When my object uses another object's functionality as is without changing it.
Composition: My object consists of other objects which in turn cannot exist after my object is destroyed-garbage collected.
Aggregation: My object consists of other objects which can live even after my object is destroyed.
Is it possible to have a few simple examples demonstrating each case, and the reasoning behind them? How else can these examples be demonstrated other than my object simply having a reference to another object(s)?
public class A {
private B b = new B();
public void methodA() {
b.methodB();
}
}
When clients of A
call methodA
, class A
delegates the call to B
's methodB
.
Rationale. Class A exposes behaviours that belong elsewhere. This can happen in single-inheritance languages where class A inherits from one class, but its clients need behaviours that are implemented in a different class. Further study.
public class A {
private B b = new B();
public void methodA() {
b.methodB( this );
}
}
The difference between delegation that involves simple forwarding and delegation that acts as a substitute for inheritance is that the callee must accept a parameter of the caller, exemplified as:
b.methodB( this );
Rationale. Allows class B
instances to use functionality available from class A
, just as class B
would if it inherited from class A
--but without inheritance. Further study.
public class A {
private B b = new B();
public A() {
}
}
Once no more references to a particular instance of class A
exist, its instance of class B
is destroyed.
Rationale. Allows classes to define behaviours and attributes in a modular fashion. Further study.
public class A {
private B b;
public A( B b ) {
this.b = b;
}
}
public class C {
private B b = new B();
public C() {
A a = new A( this.b );
}
}
Once there are no more references to a particular instance of class A
, its instance of class B
will not be destroyed. In this example, both A
and C
must be garbage collected before B
will be destroyed.
Rationale. Allows instances to reuse objects. Further study.
The names given to these simple patterns are defined by their referential relationships.