除了组合和继承以外还有第三种重用关系,称为委托。但Java并不直接支持委托。
委托介于组合和继承之间,因为如果将一个成员对象放在正在构建的类中(组合),但同时在新类中公开来自成员对象的所有方法(继承)。
例如,宇宙飞船需要一个控制模块:
public class SpaceShipControls {
void up(int velocity) {}
void down(int velocity) {}
void left(int velocity) {}
void right(int velocity) {}
void forward(int velocity) {}
void back(int velocity) {}
void turboBoost() {}
}
建造宇宙飞船的一种方法是使用继承:
public class
DerivedSpaceShip extends SpaceShipControls {
private String name;
public DerivedSpaceShip(String name) {
this.name = name;
}
@Override
public String toString() { return name; }
public static void main(String[] args) {
DerivedSpaceShip protector =
new DerivedSpaceShip("NSEA Protector");
protector.forward(100);
}
}
然而, DerivedSpaceShip 并不是一种真正的 SpaceShipControls ,即使你“告诉” DerivedSpaceShip 调用 forward()。
更准确地来说,一艘宇宙飞船包含了 SpaceShipControls,同时 SpaceShipControls 中的所有方法都暴露在宇宙飞船中。 并非一艘飞船有了控制器后就能起飞,而是飞船通过飞船控制器来起飞。委托解决了这个难题:
public class SpaceShipDelegation {
private String name;
private SpaceShipControls controls =
new SpaceShipControls();
public SpaceShipDelegation(String name) {
this.name = name;
}
// Delegated methods:
public void back(int velocity) {
controls.back(velocity);
}
public void down(int velocity) {
controls.down(velocity);
}
public void forward(int velocity) {
controls.forward(velocity);
}
public void left(int velocity) {
controls.left(velocity);
}
public void right(int velocity) {
controls.right(velocity);
}
public void turboBoost() {
controls.turboBoost();
}
public void up(int velocity) {
controls.up(velocity);
}
public static void main(String[] args) {
SpaceShipDelegation protector =
new SpaceShipDelegation("NSEA Protector");
protector.forward(100);
}
}
方法被转发到底层 control 对象,因此接口与继承的接口是相同的。但是,你对委托有更多的控制,因为你可以选择只在成员对象中提供方法的子集。
虽然Java语言不直接支持委托,但是开发工具常常支持。
但是可以通过 JetBrains Idea IDE 自动生成。