Base de Conhecimento

Injeção de Dependência em Delphi

Sempre quis saber como usar a Injeção de Dependência com Delphi? Eu criei um exemplo para você no qual passamos de um código fortemente acoplado a um belo código desacoplado em algumas etapas através da Injeção de Dependência e com a ajuda de interfaces.

Vamos começar com o exemplo a seguir:

unit DI1;

interface

type
  TLanguageTools = class
  private
    procedure CheckGrammar;
    procedure Translate;
  end;

  TWordApp = class
  private
    FLanguageTools: TLanguageTools;
  public
    constructor Create;
  end;


implementation

constructor TWordApp.Create;
begin
  FLanguageTools := TLanguageTools.Create;

  FLanguageTools.Translate;
end;

{ TLanguageTools }

procedure TLanguageTools.CheckGrammar;
begin
  //
end;

procedure TLanguageTools.Translate;
begin
  //
end;

end.

Como você pode ver, não há nada de errado com o código em princípio. É um código Delphi válido e funciona. No entanto, há algumas observações a serem feitas. Primeiro de tudo, o código é fortemente acoplado; a classe TWordApp não só depende da classe TLanguageTools, mas você não pode nem mesmo estender a classe TLanguageTools com funcionalidade extra. Mesmo que você substitua a classe TLanguageTools com, por exemplo, TEnglishLanguageTools, TWordApp simplesmente usa a classe base TLanguageTools.

Podemos fazer melhor do que isso! Uma primeira grande melhoria é remover a dependência do construtor Criar, e injetá-la. Injetar uma dependência pode ser feito de várias maneiras, através de propriedades, procedimentos ou construtores. Neste exemplo, eu uso o construtor. O código abaixo já tem uma dependência um pouco mais frouxa entre as duas classes:

unit DI2;

interface

type
  TLanguageTools = class
  private
    procedure CheckGrammar;
    procedure Translate;
  end;

  TWordApp = class
  private
    FLanguageTools: TLanguageTools;
  public
    constructor Create(ALanguageTools: TLanguageTools);
  end;


implementation

constructor TWordApp.Create(ALanguageTools: TLanguageTools);
begin
  FLanguageTools := ALanguageTools;

  FLanguageTools.Translate;
end;


{ TLanguageTools }

procedure TLanguageTools.CheckGrammar;
begin
  //
end;

procedure TLanguageTools.Translate;
begin
  //
end;

end.

Como você pode ver no exemplo, ainda estamos usando a classe TLanguageTools. Entretanto, agora é possível substituir esta classe TLanguageTools, e dar esta nova classe à classe TWordApp. E na verdade, esta é a base da classe Dependency Injection. Seu código é muito mais frouxamente acoplado e reutilizável.

Usando interfaces, podemos ir um passo além. É possível descrever a funcionalidade da classe TLanguageTools em diferentes interfaces, e passá-la para a classe TWordApp. Desta forma, programamos contra abstrações, e não contra implementações.

unit DI3;

interface

type
  IGrammarChecker = interface
    ['{FED7BA76-0EDE-40E7-BABB-16BCFE76F6DF}']
    procedure CheckGrammar;
  end;

  ITranslator = interface
    ['{C1F1092F-3589-49E5-8F22-33E8D7587A8B}']
    procedure Translate;
  end;


  TLanguageTools = class(TInterfacedObject, IGrammarChecker, ITranslator)
  private
    procedure CheckGrammar;
    procedure Translate;
  end;

  TWordApp = class
  private
    FTranslator: ITranslator;
  public
    constructor Create(ATranslator: ITranslator);
  end;

implementation

constructor TWordApp.Create(ATranslator: ITranslator);
begin
  FTranslator := ATranslator;

  FTranslator.Translate;
end;

procedure TLanguageTools.CheckGrammar;
begin
  //
end;

procedure TLanguageTools.Translate;
begin
  //
end;

end.

Como você pode ver, a classe TWordApp não depende mais da classe TLanguageTools. Desde que passemos para o construtor uma instância com uma implementação da interface do ITranslator, o código apenas funcionará. Não precisamos mais nem mesmo da classe TLanguageTools.

Assim, com a ajuda da Injeção de Dependência e com interfaces, obtemos um código de fonte agradável, desacoplado e bem conservado.

Torne-se um herói da GDK Delphi! Subscreva aqui para nossa lista de correio da Delphi!

Written by Marco Geuze
Diretor

Contato

Deixe-nos ajudá-lo a realizar seus sonhos.