zoukankan      html  css  js  c++  java
  • Delphi下IOC 模式的实现(反转模式,即Callback模式)

    IOC英文为 Inversion of Control,即反转模式,这里有著名的好莱坞理论:你呆着别动,到时我会找你。Ioc模式是解决调用者和被调用者之间关系的模式,可以有效降低软件的耦合度,并适合团队开发,使用这种模式需要首先设计一个好的框架,也可以称之为IoC容器(可能这样的说法在Java世界更Cool J)。其实Windows内部就存在这样的模式,称之为Callback(回调),在Delphi 的源代码中也有很多这样的方式。看一个例子:
           可以打开下面两个文件
           $(Delphi)SourceVclDB.pas
           $(Delphi)SourceVclDBLogDlg.pas
           第二个文件是一个需要用户填写登录用户名和密码的对话框,显然这属于用户交互层,
    我们不希望在DB.pas(数据逻辑层)中直接调用这个功能,Delphi是这样实现的:
           DB.pas #2282 有这样的声明:
           LoginDialogProc: function (const ADatabaseName: string; var AUserName, APassword: string): Boolean;
           LoginDialogProc 被定义为函数类型变量。
           在DBLogDlg.pas #132
            initialization
                  if not Assigned(LoginDialogProc) then LoginDialogProc := LoginDialog;
           也就是在DBLogDlg.pas单元初始化阶段给DB.Pas中的LoginDialogProc赋予实现函数。
    我觉得这个例子已经足够把问题说得清楚了。
    当然这并非实现IoC的唯一方法,对于不同的语言都有自己的特性,上面的方法可能比较古老的一种,通过函数指针来实现,其他的方法还有
           一:封装为接口
                  我们看到在DB.pas 中声明了很多类似的函数变量,我们可以将其封装为一个接口
           IDBDlogInterface = Interface
      ['{06B5DEAC-0BB1-4658-91F6-E78004DF131D}']
      LoginDialogProc: function (const ADatabaseName: string; var AUserName, APassword: string): Boolean;
      LoginDialogExProc: function (const ADatabaseName: string; var AUserName, APassword: string; NameReadOnly: Boolean): Boolean;
      RemoteLoginDialogProc: function (var AUserName, APassword: string): Boolean;
    end;
    然后申明一个全局的接口类型变量
    Var
           DBDialog : IDBDialogInterface ;
           然后在其他单元实现这个接口,并初始化时赋值到这个接口变量。
           二:注册机制的IoC
           这个例子稍微复杂一些,但是似乎更使用
           我们在一个窗口上放置了一个pageControl,我们知道一个pageControl上可以放置多个pageControl,而且这多个pageControl功能相对独立,没有耦合。我们可以这样做:建立这个主窗体放置一个空的PageControl,然后声明一个TInterfaceList变量用来存储PageControl的具体实现。每一个PageControl动态创建,使用注册的Frame来填充。代码如下:
    unit frmStartPage;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs,  StdCtrls, ImgList,Contnrs, ComCtrls, ExtCtrls;
     
    Type
      //填充pageControl的Frame基类
      TPageFrame = class(TFrame)
      protected
        function Caption :String ; virtual; abstract;
      end;
          
      TPageFrameClass = class of TPageFrame ;
          
      TStartPage = class(TForm)
        PageControl1: TPageControl;
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    var
      StartPage :TStartPage ;
      RegTabSheetClasses: TClassList;
      procedure RegisterStartPageTabSheet( AFrameClass :TPageFrameClass);
     
    implementation
     
    {$R *.dfm}
     
     
    procedure TStartPage.FormCreate(Sender: TObject);
    var
      i:integer;
      lTabSheet : TTabSheet;
      lFrame : TPageFrame;
    begin
      for i:= 0 to RegTabSheetClasses.Count -1 do
      begin
        lTabSheet := TTabSheet.Create(PageControl1);
        lFrame := TPageFrameClass( RegTabSheetClasses[i]).Create(self) as TPageFrame;
        lTabSheet.Caption := lFrame.Caption ;
        lFrame.Align := alClient;
        lTabSheet.InsertControl(lFrame);
        lTabSheet.PageControl := PageControl1;
        lTabSheet.PageIndex := 0 ;
      end;
    end;
     
    procedure RegisterStartPageTabSheet( AFrameClass :TPageFrameClass);
    begin
      RegTabSheetClasses.Add(AFrameClass);
    end;
     
    initialization
      RegTabSheetClasses := TClassList.Create ;
    finalization
      RegTabSheetClasses.Free;
    end. 
           
     
    unit Unit2;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
      Dialogs,frmStartPage, StdCtrls;
     
    type
      TFrame2 = class(TPageFrame)
        Label1: TLabel;
      private
        { Private declarations }
      protected
        { Public declarations }
        function Caption :String ; override;
      public
      end;
     
    implementation
     
    {$R *.dfm}
    { TFrame2 }
     
    function TFrame2.Caption: String;
    begin
      result := 'Frame1';
    end;
     
    initialization
      RegisterStartPageTabSheet(TFrame2);
     
    end.

    转至:http://tb.blog.csdn.net/

    http://www.cnblogs.com/sonicit/archive/2008/04/08/1141831.html

  • 相关阅读:
    java web 资源文件读取
    页面跳转
    验证码的随机图片
    spring 注解
    回文字符串系列问题
    【leetcode】Find All Anagrams in a String
    斐波那契数列
    【leetcode】 First Missing Positive
    Trapping Rain Water
    区间合并问题
  • 原文地址:https://www.cnblogs.com/findumars/p/6329670.html
Copyright © 2011-2022 走看看