Share Button

Quando trabalho com MVCBr o “model” é responsável em executar ações do aplicativo. Um aplicativo, mesmo os mais simples, poderá consumir um número considerável de Models para levar a cabo a execução de todas as ações.
Não será raro que sua aplicação requeira carregar uma dezena de “model” em um único “controller” – nem sempre irá utilizá-los de imediato ou todos ao mesmo tempo. Nada mais sensato postergar a criação do objeto para o momento que for necessário sua execução e concluído a ação liberá-lo da memória sem perder o acesso a classe para posterior execução de novas ações.

Postergar a criação do objeto é chamado de “Lazy Load” – carga tardia do objeto.

Estratégia

A estratégia para criar o objeto tardiamente é criar um “Patterns Adapter” para que faça o controle da classe a ser criada no momento que for necessária, ou seja, ao instânciar o “adapter” ele deve guardar qual a classe que irá criar somente quando for chamado para executar a ação requerida.

Para executar uma carga tardia da classe o MVCBr utiliza a classe TModelAdapterFactory como mostra a declaração a seguir:


  TModelAdapterFactory<T: Class> = class(TModelFactory, IModel,
    IModelAdapter<T>)
  private
    FInstanceClass: TComponentClass;
    FInstance: T;
    function GetInstance: T; virtual;
    constructor CreateInternal; overload; virtual;
  public
    constructor Create; overload;
    class function New(AController: IController)
      : TModelAdapterFactory<T>; static;
    destructor Destroy; override;
    procedure Release; override;
    property Instance: T read GetInstance;
    procedure FreeInstance; virtual;
  end;

Criando o Adapter

Explorando o código do TModelAdapterFactory notará que a inicialização é permitida através da “class function New” que guarda as informações da sub-classe a ser criada tardiamente.

Durante a criação do adapter não haverá inicialização da sub-classe, que só poderá ser criada ao chamar a propriedade “Instance” – momento criar e retorna uma instância da sub-classe;

Exemplo:


  /// declarando a variável para o Adapter - passando tipo da sub-classe 
  var LMeuAdapter : TModelAdapterFactory<TDataModuleXXX>; 

.....
  /// criando o adapter 
  LMeuAdpater := TModelAdapterFactory<TDataModuleXXX>.new(   FController );

  /// consumindo a sub-classe
  LMeuAdapter.Instance.ExecutarMeuProcedimento;  // exemplo de chamada de um método da sub-classe

Sendo o adapter uma herança de “IModel”, em geral será utilizado como uma instância ligada a um controller no MVCBr – neste caso dispensa a declaração da variável e permite tratar o MODEL como outro MODEL comum ligado ao seu controller.

    /// adicionando o model para o controller no CreateModels do Controller
    add(     TModelAdapterFactory<TDataModuleXXX>.New(FController)   );

Quando usar um Adapter

Há duas razões para querer utilizar um Adapter como um MODEL.
1. O primeiro deles é quando você quer importar uma classe para o MVCBr sem fazer as alterações da classe existente – irá permitir consumir a sub-classe como um MODEL mesmo quando a classe não implementa a interface de um MODEL – a sub-classe será acessível pela propriedade “Instance” ;
2. Quando um objeto requeira “instânciar” e “liberar” de forma formal sem interferência da contagem de referência. Casos práticos foram detectado necessidade da utilização do Adapter quando se trabalha com TDataModule – para melhorar o controle e liberação da instância;

Liberação temporária da Instância

Um bom motivo para utilizar carga tardia de um classe pode ser justificada para manter carga de memória somente dos objetos que sejam necessário para a ação e liberá-los tão logo termine sua utilização – para liberar a instância utilizar “FreeInstance” que libera somente a instância da sub-classe mantendo a Adapter ativo.

Git: Projeto MVCBr (quando deste artigo o código corrente Branch DEV); Localizar UNIT: MVCBr.Model para ver o código;