何时该使用"委托"(Delegation)?

原创 2001年05月11日 20:45:00

由于类别继承和物件组合是物件导向软体设计的两个主要方法﹔在不便使用继承的场合里﹐常使用物件组合﹐此时也常用委托观念。<?XML:NAMESPACE PREFIX = O />

 

 


     物件A 把外界传来的讯息" 转送" 给物件B ﹐由B 处理之﹐我们称物件A 委托物件B 。当一群物件互相沟通分工合作时常用妥托观念。虽然C++ 并未直接支援委托功能﹐但能间接地表达出来。由于类别继承(Class Inheritance) 和物件组合(Object Composition)是物件导向软体设计的两个主要方法﹔在不便使用继承的场合里﹐常使用物件组合﹐此时也常用委托观念。例如﹐有个" 长方形" 类别﹕

      <?XML:NAMESPACE PREFIX = V />dele8.1.gif

    接着想设计个" 正方形" 类别﹐大多数人会先想到继承功能﹕

         dele8.2.gif

如此就可重复使用(Reuse) Area()函数了。

    这个继承结构有些美中不足之处﹐例如SquareRectangle 继承了SetWidth()SetHeight() 函数﹐对Square()而言是无用而且有害。万一呼叫到SquareSetWidth()﹐则Square4 边就不等长了﹗这时﹐可改用物件组合方式来代替继承﹕

 

dele8.3.gif   Square之物件接到外界传来的Area()讯息时﹐就委托Rectangle 之物件代为处理。以C++ 表达如下﹕

 

//// 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类别﹐就无上述的副作用了。但也些缺点﹕rectangle 值是在程式执行时才确定的﹐也就是委托关系是在执行时才建立起来。一旦rectangle 值改变了﹐就改变委托的对象。所以委托是很有弹性的,但却常令程式更复杂。反过来,继承关系是在程式编译时就确定了﹐能使程式较清楚﹐但在执行时无法改变继承关系﹐弹性较小。因之﹐继承和委托皆能达到重复使用(Reuse)之目的﹐各有所长各有所短﹐相辅相成才是完美的。简单规则是﹕

 

   「优先考虑使用继承﹐若觉得牵强﹐

     就考虑用委托」

 

请看下述例子﹐有个" 圆形" 类别以及" 正方形" 类别﹐共同衍生出CR类别﹕

 

dele8.4.gif    CR类别的Draw()会先呼叫Square::Draw()绘出正方形﹐再呼叫Circle::Draw()绘出正方形的内接圆。以C++ 表示为﹕

 

//// 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()

             { return y; }

    virtual int GetLength() 

             { return r*2; }

    void Draw() { ... }

 };

    SquareDraw()函数绘图时﹐会先从CR取得正方形的中心点座标(x,y) 值﹐且取得正方形的边长﹐然后才画出正方形。

    一般而言﹐多重继承(Multiple Inheritance)常有些副作用﹐例如名称的冲突等。为了避免上述双重继承﹐可改用委托方法,如下图。

 

dele8.5.gifC++ 表示如下﹕

 

//// Square ////

class Square

   {

     Draw(CR *pcr)

       {  pcr->GetX()

          pcr->GetY()

          ....

       }

   };

 

class CR : public Circle

  {

    Square *square;

   public:

    int GetX()  { return x; }

    int GetY()  { return y; }

    int GetLength  { return r*2; }

    void Draw()

          { square->Draw(this); }

    ........

  };

 

 

    继承和委托都是重复使用另一类别或物件中的函数。例如﹐CR继承Square时﹐CR使用SquareDraw()来绘出正方形﹔当继承改为委托时﹐也是一样由SquareDraw()来担任绘正方形的工作。所以﹐若觉得CR继承Square有些麻烦时﹐应可考虑使用委托。虽然委托会令程式复杂些﹐但勉强使用继承﹐后遗症将更大。因为副作用可能会延续到CR的各子孙类别﹗

关于使用C++11中委托构造函数

今天在读《C++Primer》时读到委托构造函数一节,书中关于委托构造函数是这样描述的: 一个委托构造函数使用它所属的类的其他构造函数执行自己的初始化过程,或者说它把自己的一些(或者全部)职责委托...
  • huangtiao2509
  • huangtiao2509
  • 2017年06月29日 11:18
  • 319

JavaScript事件代理和委托(Delegation)

JavaScript事件代理和委托(Delegation)
  • qq_36242361
  • qq_36242361
  • 2017年08月02日 14:35
  • 123

JavaScript事件代理和委托(Delegation)

目录(?)[-] JavaScript事件代理事件冒泡及捕获jQuery和Dojo中delegate函数优点在JavaScript编程中使用代理 在javasript中dele...
  • majian_1987
  • majian_1987
  • 2013年02月19日 15:37
  • 43217

JavaScript事件代理和委托(Delegation)

http://www.cnblogs.com/owenChen/archive/2013/02/18/2915521.html 在javasript中delegate这个词经常出现,看字...
  • SalmonellaVaccine
  • SalmonellaVaccine
  • 2015年01月09日 08:15
  • 449

JavaScript事件代理和委托(Delegation)

在javasript中delegate这个词经常出现,看字面的意思,代理、委托。那么它究竟在什么样的情况下使用?它的原理又是什么?在各种框架中,也经常能看到delegate相关的接口。这些接口又有什么...
  • jlds123
  • jlds123
  • 2013年02月19日 15:14
  • 1829

JavaScript事件代理和委托(Delegation)

为啥要事件委托呢? 首先每个函数都是对象,都会占用内存;内存中的对象越多,性能就越差。其次,必须事先指定所有事件处理程序而导致的DOM访问次数,会延迟整个页面的交互就绪时间。利用事件委托,只需要在D...
  • caowen414
  • caowen414
  • 2016年03月30日 10:12
  • 223

JavaScript事件代理和委托(Delegation)

JavaScript事件代理 首先介绍一下JavaScript的事件代理。事件代理在JS世界中一个非常有用也很有趣的功能。当我们需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点而将...
  • YLXB2
  • YLXB2
  • 2016年10月09日 20:14
  • 160

JavaScript事件代理和委托(Delegation)

在javasript中delegate这个词经常出现,看字面的意思,代理、委托。那么它究竟在什么样的情况下使用?它的原理又是什么?在各种框架中,也经常能看到delegate相关的接口。这些接口又有什么...
  • zhawabcd
  • zhawabcd
  • 2017年12月12日 17:06
  • 22

委托的使用与原理简析

委托的使用与原理简析:委托为什么本质上是数据类型?委托变量直接执行了方法背后原理是什么?多播委托是怎么实现的?...
  • shuaihj
  • shuaihj
  • 2016年11月06日 19:03
  • 1693

js | event delegation 事件委托之双十一

眼看双十一就要来了,周围的人寻思估摸着要“剁手,吃土”了,购物车里,那是加了一件又一件。话说马云师兄,咳咳,鄙人不才,同一母校,导开了电商之路后,那快递,可是摞了一叠,叠了再摞,纸山袋海。额,不好意思...
  • anmoran
  • anmoran
  • 2016年11月02日 10:31
  • 312
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:何时该使用"委托"(Delegation)?
举报原因:
原因补充:

(最多只允许输入30个字)