Инъекция зависимостей Delphi: Framework против конструктора делегирования - PullRequest
11 голосов
/ 10 мая 2011

Зачем вам использовать Dependency Injection Framework, если вы можете просто использовать следующий шаблон?

unit uSomeServiceIntf;

interface

type
  ISomeService = interface
    procedure SomeMethod;
  end;

var
  CreateSomeService: function: ISomeService;

implementation

end.

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.

unit uInitializeSystem;

interface

procedure Initialze;

implementation

uses
  uSomeServiceIntf,
  uSomeServiceImpl;

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

end.

Я пытаюсь понять преимущества использования фреймворка вместо этого, но пока вижу только преимущества этого простого подхода:

1) Параметризованные конструкторы легче реализовать. Например.: вар 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.

Что бы вы посоветовали использовать инфраструктуру DI вместо этого подхода?

Как это будет выглядеть при использовании DI-фреймворка?

Насколько я знаю, если бы вы использовали платформу DI, вы бы зарегистрировали конкретный класс в интерфейсе, и тогда потребители системы попросили бы реализацию для данной платформы. Так что будет зарегистрирован звонок:

DIFramework.Register(ISomeInterface, TSomeInterface)

и когда вам нужна реализация ISomeInterface, вы можете попросить DI-фреймворк:

var
  someInterface: ISomeInterface;
begin
  someInteface := DIFrameWork.Get(ISomeInterface) as ISomeInterface;

Теперь, очевидно, если вам нужно передать параметры для создания ISomeInterface, все это усложняется с помощью DIFramework (но просто с подходом, описанным выше).

1 Ответ

6 голосов
/ 29 мая 2011

В вашем случае вы должны знать название заводской функции ptr (var CreateSomeService) заранее, во время разработки.Конечно, интерфейс и функция ptr объединены в одном модульном файле Delphi, но это всего лишь реликвия Delphi, глобальная переменная не является поточно-ориентированной и не защищена от доступа.

А что, если вы получили интерфейс во время выполнения в результате какой-либо функции или чтения из файла конфигурации - вы не знаете, какую фабричную функцию вызывать для получения фактического экземпляра разработчика.

DIFrameWork.Get(ISomeInterface) as ISomeInterface скрывает от вас заводскую функцию, поэтому вам нужен только интерфейс, а не интерфейс и заводская функция.Если вы попытаетесь скрыть заводскую функцию, вам также придется скрыть параметры.(и в итоге получится нечто похожее на эту структуру DI).

...