MVCBr – Lazy Load Model – Um “wrapper” para carga tardia do “Model”

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:

[code]

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;

[/code]

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:
[code]

/// 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

[/code]

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.

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

[/code]

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;

3 comentários

  1. Excelente o artigo porém há um pequeno erro de grafia no título, Acredito que a palavra seria ‘Tardia’

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *