zoukankan      html  css  js  c++  java
  • Delphi implements 委托 转

    Delphi 里的接口聚合的写法转 百毒空间,百毒不侵

    unit Unit1;

    {-----------------------------------------------------------------------------

      本程序演示接口委托聚合:

      TMyClass 拥有并实现了 IMyTask 接口

      TMyPlan 类拥有 IMyTask 接口,但没有去实现这个接口里的 SayHell 方法,而是通过

      property MyTask: IMyTask read FMyClass implements IMyTask; 语句,将这个实现委托给内部的 FMyClass 接口实现。

      传统的面向类的代码,当做一个包装类,包装多个子类在里面的时候,要在包装类的 public 里

      再实现一次子类里的方法,在实现的方法里再调用子类的方法。这种办法也有人称为【委托】。

      如果采用接口委托,则不用重复写代码,直接写一句:

      property MyTask: IMyTask read FMyClass implements IMyTask; 则包装类

      就不用在 public 里再次重复实现一次接口里的函数方法等等了。这种办法也有人称为【聚合】

      以下代码测试通过。

      pcplayer 2011-10-23 星期日。

    -----------------------------------------------------------------------------}

    interface

    uses

      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

      Dialogs, StdCtrls;

    type
    IMyTask = Interface
        ['{1B9D204E-1662-4280-A8E6-D7F518A425F5}']
        function SayHello: string;
      End;

      TMyClass = class(TInterfacedObject, IMyTask)
      private
      public
        function SayHello: string;//实现
      end;
      TMyPlan = class(TInterfacedObject, IMyTask)
      private
        FMyClass: IMyTask;
      public
        constructor Create;  //没有实现   SayHello ,通过  FMyClass实现SayHello
        property MyTask: IMyTask read FMyClass implements IMyTask;
      end;
      TForm1 = class(TForm)

        Button1: TButton;

        Label1: TLabel;

        procedure Button1Click(Sender: TObject);

      private

        { Private declarations }

      public

        { Public declarations }

      end;

    var

      Form1: TForm1;

    implementation

    {$R *.dfm}

    { TMyClass }

    function TMyClass.SayHello: string;
    begin
      Result := 'Hello';
    end;

    { TMyPlan }
    constructor TMyPlan.Create;
    begin
      inherited;
      FMyClass := TMyClass.Create as IMyTask;
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    var
      MyPlan: IMyTask;
    begin
      MyPlan := TMyPlan.Create;
      Label1.Caption := MyPlan.SayHello;
      MyPlan := nil;

    end;

    end.

    delphi中接口的委托和聚合  转http://blog.163.com/liang_liu99/blog/static/884152162009827104444775/

    委托:
    当存在两个接口,和两个类;这两个类分别实现了两个接口;
    现在需要一个创建一个类支持这两个接口,为了不采用重复的工作
    就可以在Create方法中,创建实现了这两个接口的类,然后委托这两个实现了接口的方法去实现功能
    代码如下:
    type
    ISomeIntf = interface
    ['{E3285C36-B73B-4F36-8AA1-904F76FBC9E8}']
        procedure Msg;
    end;

    IOtherIntf = interface
    ['{271DC3C3-E29E-4D2A-A05D-C3DAC641D723}']
        function Check: Boolean;
    end;

    TSome( ISomeIntf)
    protected
        procedure Msg;
    end;

    TOther (IOtherIntf)
    protected
        function Check: Boolean;
    end;

    TIntf (IUnknown, ISomeIntf, IOtherIntf)
    private
        // declare objects to delegate to
        FSomeClass: ISomeIntf;
        FOtherClass: IOtherIntf;
    protected
        // ISomeIntf
        procedure Msg;
        // IOtherIntf
        function Check: Boolean;
    public
        constructor Create;
    end;

    { TIntfClass }

    constructor TIntfClass.Create;
    begin
    inherited;
    // create objects for delegation
    FSomeClass:= TSomeClass.Create;
    FOtherClass:= TOtherClass.Create;
    end;

    function TIntfClass.Check: Boolean;
    begin
    // delegate work
    Result:= FOtherClass.Check;
    end;

    procedure TIntfClass.Msg;
    begin
    // delegate work
    FSomeClass.Msg;
    end;


    聚合
    关键字implements使得一个类通过对象或者接口属性引用(已经实现了接口的类引用)来实现这个类所支持的接口,不用为起支持的接口编写代码。
    示例代码如下:
    type
    ISomeIntf = interface
    ['{E3285C36-B73B-4F36-8AA1-904F76FBC9E8}']
        procedure Msg;
    end;

    IOtherIntf = interface
    ['{271DC3C3-E29E-4D2A-A05D-C3DAC641D723}']
        function Check: Boolean;
    end;

    TSome ISomeIntf)
    protected
        procedure Msg;
    end;

    TOther IOtherIntf)
    protected
        function Check: Boolean;
    end;

    TIntf IUnknown, ISomeIntf, IOtherIntf)
    private
        FSomeClass: ISomeIntf;
        FOtherClass: TOtherClass;
    protected
        // interface type reference property
        property SomeIntf: ISomeIntf read FSomeClass implements IUnknown, ISomeIntf;
        // object type reference property
        property OtherIntf: TOtherClass read FOtherClass implements IOtherIntf;
    end;

    但是必须在适当的时候对引用的类初始化;
    constructor TIntfClass.Create;
    begin
    FSomeClass:= TSomeClass.Create;
    FOtherClass:= TOtherClass.Create;
    end;

    聚合实际上是委托在代码上的一种简化;对于接口引用和对象引用,区别在于:接口引用比较安全,在它Relrease之前可以安全的引用,但对象引用可能被意外的
    Free掉,所以在使用对象引用时,必须很好的控制对象引用的计数逻辑。一般通过接口控制类的生存周期。


    Delphi的接口委托示例  http://www.cnblogs.com/MurphyAefe/articles/1741825.html

    {
      说明:该事例实现的效果,在单个应用或代码量小的项目中,可以完全不用接口委托来完成。
      之所以采用委托接口,主要是应用到:已经实现的接口模块中,在不改变原有代码的情况下,
      需要对其进行扩展;原始模块只需要开放部分功能,但又不能暴露实现细节的场合;

    }

    unit TestUnit;

    interface

    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;

    const
      TestMsgGUID: TGUID = '{4BE80D5E-D94B-42BE-9114-077DC2708451}';

    type
      //原始接口中新增需要暴露给其它模块的接口定义,公用部分
      ITestMsg = interface
        ['{4BE80D5E-D94B-42BE-9114-077DC2708451}']
        procedure ShowTestMsg;
      end;

      //---------------------------------服务模块
      //基类对象,只需要开放ShowTestMsg方法给外部,所以做为按口的实现基类
      TBaseTestMsg = class(TInterfacedObject, ITestMsg)
      public
        //.... 模块已存在的老代码....

        //新开放的接口代码方法
        procedure ShowTestMsg; virtual;     //申明成虚拟方法,以便继承类可以重载
      end;

      //---------------------------------接口委托对象定义
      TTestMsgClass = class(TInterfacedObject, ITestMsg)
      private
        FTestMsg: ITestMsg;
      public
        property Service: ITestMsg read FTestMsg implements ITestMsg;

        constructor Create(AClass: TClass);
        constructor CreateEx(AClass: TClass);      //另一种用法, 不采用TBaseTestMsg做为基类创建委托实例
        destructor Destroy; override;
      end;

      //----------------------------------外部引用的业务模块
      //完成具体业务的委托实例
      TETestMsg = class(TInterfacedObject, ITestMsg)
      public
        procedure ShowTestMsg;
      end;

      //完成具体业务的委托实例
      TCTestMsg = class(TInterfacedObject, ITestMsg)
      public
        procedure ShowTestMsg;
      end;


      TForm1 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
        procedure DoTest(AClass: TClass; ACreateEx: Boolean = False);     //测试方法
      end;

    var
      Form1: TForm1;

    implementation

    {$R *.dfm}

    { TBaseTestMsg }

    procedure TBaseTestMsg.ShowTestMsg;
    begin
    end;

    { TTestMsgClass }

    constructor TTestMsgClass.Create(AClass: TClass);
    var
      vObj: TBaseTestMsg;
    begin
      vObj := TBaseTestMsg(AClass.NewInstance);
      FTestMsg := vObj.Create;
    end;

    constructor TTestMsgClass.CreateEx(AClass: TClass);
    begin
      //该方法不采用TBaseTestMsg做为基类创建委托实例,更通用更灵活
      (AClass.NewInstance.Create).GetInterface(TestMsgGUID, FTestMsg);
    end;

    destructor TTestMsgClass.Destroy;
    begin
      FTestMsg := nil;
      inherited;
    end;


    { TETestMsg }

    procedure TETestMsg.ShowTestMsg;
    begin
      ShowMessage('TETestMsg Msg:' + 'OK');
    end;

    { TCTestMsg }

    procedure TCTestMsg.ShowTestMsg;
    begin
      ShowMessage('TCTestMsg 消息:' + '好的');
    end;

    //--------------------以下为测试代码--------------------------------

    procedure TForm1.DoTest(AClass: TClass; ACreateEx: Boolean);
    var
      vClass: TTestMsgClass;
      vTest: ITestMsg;
    begin
      if ACreateEx then
        vClass := TTestMsgClass.CreateEx(AClass)
      else
        vClass := TTestMsgClass.Create(AClass);

      try
        vTest := vClass;
        vTest.ShowTestMsg;
      finally
        vTest := nil;
        FreeAndNil(vClass);
      end;
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    begin
      DoTest(TETestMsg);
      DoTest(TCTestMsg);
    end;

    procedure TForm1.Button2Click(Sender: TObject);
    begin
      DoTest(TETestMsg, True);
      DoTest(TCTestMsg, True);
    end;

    end.


  • 相关阅读:
    2019CSUST集训队选拔赛题解(二)
    2019CSUST集训队选拔赛题解(一)
    Dilworth定理
    直线石子合并(区间DP)
    后缀自动机 个人学习笔记
    HDU_6709 CCPC网络赛H 优先队列 贪心
    2019省赛翻车记
    【挖坑】某场组队训练找到的想要挖一挖的东西
    暑假补题需要点的技能点
    QAQorz的训练记录
  • 原文地址:https://www.cnblogs.com/luckForever/p/7254987.html
Copyright © 2011-2022 走看看