Table of contents |
2 Complex Java Example 3 Criticisms 4 References |
In this example, the class C has method stubs that forward the methods f() and g() to class A. Class C pretends that it has attributes of class A.
class C {
// delegation
A a = new A();
void f() { a.f(); }
void g() { a.g(); }
// normal attributes
X x = new X();
void y() { /* do stuff */ }
}
void main() {
C c = new C();
c.f();
c.g();
}
By using interfaces, delegation can be made more flexible and typesafe. In this example, class C can delegate to either class A or class B. Class C has methods to switch between classes A and B. Including the implements clauses improves type safety, because each class must implement the methods in the interface. The main tradeoff is more code.
class A implements I {
void f() { system.out.println("A: doing f()"); }
void g() { system.out.println("A: doing g()"); }
}
class B implements I {
void f() { system.out.println("B: doing f()"); }
void g() { system.out.println("B: doing g()"); }
}
void f() { i.f(); }
void g() { i.g(); }
// normal attributes
void toA() { i = new A(); }
void toB() { i = new B(); }
}
void main() {
C c = new C();
c.f();
c.g();
}
Because this is a pattern, developers can make many kinds of mistakes. The developer could forget method in the simple version. The developer could mistype the name of one attribute.
This pattern typically sacrifices speed optimization in favour of enhanced clarity of abstraction.
See also Design pattern and Post-object programming.Simple Java Example
class A {
void f() { system.out.println("A: doing f()"); }
void g() { system.out.println("A: doing g()"); }
}
Complex Java Example
interface I {
void f();
void g();
}
class C implements I {
// delegation
I i = new A();
Criticisms
References