Decorator uses Delegation, but in a very specific way.
Delegation (or composition) is not as much a pattern as a general way to build complex behavior by coordinating use of several other objects. It’s often used in a set or static way. By “set or static” I mean something like this:
class Delegator {
private final ClassA a = new ClassA();
private final ClassB b = new ClassB();
public void doWork() {
a.setup();
final ResFromA resa = a.getRes();
b.setup();
b.consume(resa);
}
}
Note that Delegator does not share any type or interface with either ClassA
or ClassB
, and knows the exact type of both a
and b
.
Decorator is a dynamic way to use delegation to add behavior to a logical entity at runtime. In Decorator all entities share a common interface, and use delegation to concatenate their work.
public interface Item {
public void drawAt(final int x, final int y);
}
public class CircleAround implements Item {
private final Item wrapped;
private final int radius;
public CircleAround(public final Item wrapped, public final int radius) {
this.wrapped = wrapped;
this.radius = radius;
}
public void drawAt(final int x, final int y) {
// First handle whatever we are wrapping
wrapped.drawAt(x,y);
// Then add our circle
Graphics.drawCircle(x, y, radius);
}
}
Note that unlike the first example, CircleAround
does not know the exact type of the item that it wraps, and shares a common interface with it.