• Delphi下IOC 模式的实现


        IOC英文为 Inversion of Control,即反转模式,这里有著名的好莱坞理论:你呆着别动,到时我会找你。Ioc模式是解决调用者和被调用者之间关系的模式,可以有效降低软件的耦合度,并适合团队开发,使用这种模式需要首先设计一个好的框架,也可以称之为IoC容器(可能这样的说法在Java世界更Cool J)。其实Windows内部就存在这样的模式,称之为Callback(回调),在Delphi 的源代码中也有很多这样的方式。看一个例子:
           可以打开下面两个文件
           $(Delphi)\Source\Vcl\DB.pas
           $(Delphi)\Source\Vcl\DBLogDlg.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/
  • 相关阅读:
    NoInstall_Mysql
    说话
    我是一名博客新人
    pom.xml报错
    模板——链表模板、有序链表模板及测试
    模板——函数模板
    模板——类模板
    MDI程序演示
    容器和算法2 C++快速入门48(完)
    MDI程序演示
  • 原文地址:https://www.cnblogs.com/sonicit/p/1141831.html
Copyright © 2020-2023  润新知