Base de Conhecimento

Spring4D factory pattern

Que opções existem na estrutura do Spring4D que não conhecemos, mas que são muito úteis? Bem, na verdade, são muitos. Um deles é o Factory Pattern. Ele é muito útil quando você deseja aplicar o padrão open/closed principle. Seu código está aberto para extensão, mas fechado para modificação.

Um exemplo clássico é trabalhar com enumerações ou números que indicam um determinado estado. Isso cria rapidamente todos os tipos de estruturas condicionais que precisam ser adaptadas assim que um novo status ou valor é adicionado. No exemplo abaixo, determinado código é executado dependendo do status de uma fatura. Para dividir o código, foi aplicado o Factory pattern.

Essa é a definição de Invoice e status:

type
  {$SCOPEDENUMS ON}
  TInvoiceStatus = (New, Sent, Overdue, Paid);
  {$SCOPEDENUMS OFF}

  TInvoice = class
  public
    function Status: TInvoiceStatus;
  end;
Para usar o Factory pattern, incluímos a unidade Spring.DesignPatterns. Em seguida, definimos a Factory pattern. Ela consiste em um valor-chave e uma função que retorna o método que você deseja executar. Isso parece complexo, mas não é tão ruim. Em nosso caso, o valor-chave é o status do Invoice (TInvoiceStatus). A função que queremos executar tem o Invoice (TInvoice) como parâmetro. A definição da Factory pattern fica assim:
type
  TProcessInvoiceProc = reference to procedure(const Invoice: TInvoice);

  TInvoiceProcessor = class
  private
    FFactory: TFactory<TInvoiceStatus, TProcessInvoiceProc >;
    procedure InitialiseFactory;
  end;

procedure TInvoiceProcessor .InitialiseFactory;
begin
  FFactory := TFactory<TInvoiceStatus, TProcessInvoiceProc >.Create;

  FFactory.RegisterFactoryMethod(TInvoiceStatus.New, ProcessInvoiceNew);
  FFactory.RegisterFactoryMethod(TInvoiceStatus.Sent, ProcessInvoiceSent);
  FFactory.RegisterFactoryMethod(TInvoiceStatus.Overdue, ProcessInvoiceOverdue);
  FFactory.RegisterFactoryMethod(TInvoiceStatus.Paid, ProcessInvoicePaid);
end;
O código acima já mostra como o Factory pattern é criada e inicializada. Associada a cada status está uma função “Process”. Essa função retorna a definição do TProcessInvoiceProc para executar o código para esse status. Você define isso da seguinte forma:
function TInvoiceProcessor .ProcessInvoiceNew: TProcessInvoiceProc;
begin
  Result := procedure(const Invoice: TInvoice)
            begin
              ShowMessage('This is a new invoice');
            end
end;

A aplicação do Factory pattern é fácil e ocorre conforme o código abaixo:

procedure TInvoiceProcessor .ProcessInvoice(const Invoice: TInvoice);
begin
  if FFactory.IsRegistered(Invoice.Status) then
  begin
    var Process := FFactory.GetInstance(Invoice.Status;)
    Process(Invoice);
  end;
end;
Dessa forma, usando o Factory pattern, seu código é fácil de dividir e melhorar.

Written by Kees de Kraker
Diretor

Contato

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