É simples: basta fazer algumas pequenas alterações no código. Vamos supor que queremos fazê-lo num datamodule chamado Cliente:
type
TCliente = class(TDataModule, IInterface, ICliente)
dspDados: TDataSetProvider;
cdsDados: TClientDataSet;
qryDados: TSQLQuery;
private
FRefCount: Integer;
FOwnerIsComponent: Boolean;
protected
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
public
procedure AfterConstruction; override;
class function NewInstance: TObject; override;
// Outros métodos e propriedades
end;
implementation
{$R *.dfm}
procedure TCliente.AfterConstruction;
begin
inherited;
FOwnerIsComponent := Assigned(Owner) and (Owner is TComponent);
InterlockedDecrement(FRefCount);
end;
function TCliente._AddRef: Integer;
begin
Result := InterlockedIncrement(FRefCount)
end;
function TCliente._Release: Integer;
begin
Result := InterlockedDecrement(FRefCount);
if (Result = 0) and not FOwnerIsComponent then
Destroy;
end;
class function TCliente.NewInstance: TObject;
begin
Result := inherited NewInstance;
TCliente(Result).FRefCount := 1;
end;
Você deve estar se perguntando: "Por que cargas d'agua eu deveria fazer isso?". Bem, desde muito tempo eu trabalho com alguns sistemas de legado nos quais eu resolvi fazer um híbrido de OO/RAD. Criei datamodules cujo nome é o nome da classe (ex.: Cliente). O datamodule contém um clientdataset que faz o acesso aos dados no DB. Ao mesmo tempo, o DM implementa uma interface (digamos, ICliente) e para que ele trabalhe com reference counting eu implementei algo parecido. Assim, eu posso fazer:
var
Cliente: ICliente;
begin
// Não preciso conhecer a classe concreta. Apenas a interface precisa ser conhecida
// Isso ajuda a criar aplicativos de baixo acoplamento e modularizados
Cliente := ClienteFactory.CriarCliente;
Cliente.ConsultarPeloCodigo('0001');
ShowMessage(Cliente.Nome)
// Não preciso dar o Free!
end;
Mas quando usado como componente eu tenho que destruí-lo manualmente:
var
Cliente: TCliente;
begin
Cliente := TCliente.Create(nil, Connection)
try
Cliente.ConsultarPeloCodigo('0001');
ShowMessage(Cliente.Nome);
finally
Cliente.Free;
end;
end;
Assim, eu mantenho o comportamento padrão de um datamodule (sem ref. Counting) e ao mesmo tempo, quando desejado, posso usar o Ref. Counting.
Com aplicativos de baixo acoplamento, a reutilização de código aumenta. A mesma idéia pode ser utilizada em Forms. Mas com os forms precisa-se ter um cuidado especial: Se você usa uma variável local para criá-lo, ao final do método, adeus form!
Use sua criatividade. E eu tenho certeza que vc vai encontrar muita utilidade para essa dica.
Eu peguei essa idéia de TXmlDocument. Ele faz exatamente a mesma coisa: quando usado como componente, não usa o mecanismo de reference counting, mas quando usado através da interface IXmlDocument, usa reference counting.
2 comentários:
"é simples" é?! kkkkkkk se umeno tu botasse um UMLzim fiva mais "simples" ainda!
kkkkkkkkkk
Eu achei... Tu num achou nao?
Postar um comentário