何时该使用委托(Delegation)?
由于类别继承和物件组合是物件导向软体设计的两个主要方法?r在不便使用继承的场合里?o常使用物件组合?o此时也常用委托观念。
物件A 把外界传来的讯息" 转送" 给物件B ?o由B 处理之?o我们称物件A 委托物件B 。当一群物件互相沟通分工合作时常用妥托观念。虽然C++ 并未直接支援委托功能?o但能间接地表达出来。由于类别继承(Class Inheritance) 和物件组合(Object Composition)是物件导向软体设计的两个主要方法?r在不便使用继承的场合里?o常使用物件组合?o此时也常用委托观念。例如?o有个" 长方形" 类别?s
接着想设计个" 正方形" 类别?o大多数人会先想到继承功能?s
如此就可重复使用(Reuse)这 Area()函数了。
这个继承结构有些美中不足之处?o例如Square从Rectangle 继承了SetWidth()及SetHeight() 函数?o对Square()而言是无用而且有害。万一呼叫到Square的SetWidth()?o则Square的4 边就不等长了?u这时?o可改用物件组合方式来代替继承?s
//// Rectangle ////
class Rectangle {
double width, height;
public:
void SetWidth(double w)
{ width=w; }
void SetHeight(double h)
{ height=h; }
double Area()
{ return width*height; }
};
class Square {
Rectangle *rectangle;
public:
Square() { rectangle = new Rectangle; }
void SetLength(double len)
{ rectangle->SetWidth(len);
rectangle->SetHeight(len);
}
double Area()
{ return rectangle->Area(); }
};
SetWidth()及SetHeight() 不属于Square类别?o就无上述的副作用了。但也些缺点?srectangle 值是在程式执行时才确定的?o也就是委托关系是在执行时才建立起来。一旦rectangle 值改变了?o就改变委托的对象。所以委托是很有弹性的,但却常令程式更复杂。反过来,继承关系是在程式编译时就确定了?o能使程式较清楚?o但在执行时无法改变继承关系?o弹性较小。因之?o继承和委托皆能达到重复使用(Reuse)之目的?o各有所长各有所短?o相辅相成才是完美的。简单规则是?s
「优先考虑使用继承?o若觉得牵强?o
就考虑用委托」
请看下述例子?o有个" 圆形" 类别以及" 正方形" 类别?o共同衍生出CR类别?s
//// Circle ////
class Circle
{
protected:
int x, y, r;
public:
Circle(int a, int b, int)
:x(a), y(b), z(c) {}
void Draw() { .... }
};
//// Square ////
class Square
{
public:
virtual int GetX()=0;
virtual int GetY()=0;
virtual int GetLength()=0;
void Draw()
{ GetX()
GetY()
....
}
};
//// class CR ////
class CR : public Circle, public Square
{
public:
virtual int GetX()
{ return x; }
virtual int GetY()