Delphi依赖注入:框架与委托构造器

RM.*_*RM. 11 delphi dependency-injection freepascal ioc-container inversion-of-control

当您可以简单地使用以下模式时,为什么要使用依赖注入框架?

unit uSomeServiceIntf;

interface

type
  ISomeService = interface
    procedure SomeMethod;
  end;

var
  CreateSomeService: function: ISomeService;

implementation

end.
Run Code Online (Sandbox Code Playgroud)
unit uSomeServiceImpl;

interface

type 
  TSomeService = class(TInterfacedObject, ISomeService)
    procedure DoSomething;
  end;

function CreateSomeService: ISomeService;

implementation 

function CreateSomeService: ISomeService;
begin
  Result := TSomeService.Create;
end;

procedure TSomeService.DoSomeThing;
begin
  ...
end;

end.
Run Code Online (Sandbox Code Playgroud)
unit uInitializeSystem;

interface

procedure Initialze;

implementation

uses
  uSomeServiceIntf,
  uSomeServiceImpl;

procedure Initialze;
begin
  uSomeServiceIntf.CreateSomeService := uSomeServiceImpl.CreateSomeService;
end;

end.
Run Code Online (Sandbox Code Playgroud)

我试图掌握使用框架而不是这样做的好处,但到目前为止我只看到了这种简单方法的好处:

1)参数化构造函数更容易实现.例如:var CreateSomeOtherService:function(aValue:string);

2)更快(容器中无需查找)

3)更简单

我就是这样用的:

unit uBusiness;
interface
[...]
implementation

uses 
  uSomeServiceIntf;
[...]
procedure TMyBusinessClass.DoSomething;
var
  someService: ISomeService;
begin
  someService := CreateSomeService;
  someService.SomeMethod;
end;

end.
Run Code Online (Sandbox Code Playgroud)

您使用DI框架而不是这种方法的理由是什么?

如何使用DI框架?

据我所知,如果你使用DI框架而不是在界面上注册具体类,那么系统的消费者会询问给定框架的实现.所以会有一个注册电话:

DIFramework.Register(ISomeInterface, TSomeInterface)
Run Code Online (Sandbox Code Playgroud)

当你需要一个ISomeInterface实现时,你可以向DI框架询问它:

var
  someInterface: ISomeInterface;
begin
  someInteface := DIFrameWork.Get(ISomeInterface) as ISomeInterface;
Run Code Online (Sandbox Code Playgroud)

现在很明显,如果你确实需要传递参数来创建一个ISomeInterface,那么使用DIFramework就会变得更加复杂(但是使用上述方法很简单).

Bor*_* B. 6

在您的情况下,您必须var CreateSomeService在设计时提前知道工厂函数ptr()的名称.当然,接口和函数ptr在同一个Delphi单元文件中耦合在一起,但这只是一个Delphi遗物,全局变量不是线程安全的,不受访问保护.

如果你在运行时有一个接口,作为一些函数或从配置文件读取的结果 - 你不知道要调用什么工厂函数来获取实现者的实际实例.

DIFrameWork.Get(ISomeInterface) as ISomeInterface隐藏工厂功能,因此您只需要接口,而不是接口和工厂功能.如果您试图隐藏工厂功能,那么您还必须隐藏参数.(最终会得到类似于DI框架的东西).