POO: Objetos quot;Auto-instanciáveisquot;
07/09/2009
0
Primeiramente, quero colocar que criar objetos na inicialização da aplicação é algo que deve ser feito com critério, uma vez que memória é alocada consumindo recursos, isto deve ser realizado apenas quando necessário (para objetos que realmente precisamos ´instanciados´ desde sempre)
Geralmente quando precisamos destes objetos sem ter que nos preocupar com sua inicialização, estes são objetos ´centrais´ que possuem uma única instância para ser utilizada por toda aplicação. Por isso, e apenas para estes casos, posto a seguir um código exemplo utilizando o padrão de projeto Singleton.
Nesta implementação o objeto não é ´instanciado´ na seção Initialization, mas sim APENAS quando for usado pelo primeira vez, em qualquer parte da aplicação. Vamos ao código:
unit MeuObjeto; uses SysUtils, Classes; type TMeuObjeto = class (TObject) private fNome: string; fLista: TStrings; public constructor Create; destructor Destroy; override; class function Instance: TMeuObjeto; property Nome: string read fNome write fNome; property Lista: TStrings read fLista; end; function MeuObjeto: TMeuObjeto; implementation var InstanciaMeuObjeto: TMeuObjeto = nil; function MeuObjeto: TMeuObjeto; begin Result := TMeuObjeto.Instance; end; constructor TMeuObjeto.Create; begin inherited Create; fLista := TStringList.Create; fNome := ´´; end; destructor TMeuObjeto.Destroy; begin fLista.Free; inherited; end; class function TMeuObjeto.Instance: TMeuObjeto; begin if InstanciaMeuObjeto=nil then InstanciaMeuObjeto := TMeuObjeto.Create; Result := InstanciaMeuObjeto; end; initialization finalization if InstanciaMeuObjeto<>nil then InstanciaMeuObjeto.Free; end.
Comentários sobre o código:
Note que foi criada uma FUNÇÃO como ponto de acesso global a instância do objeto e não uma variável. Isto garante maior poder e controle sobre a inicialização e destruição da mesma. Exemplo: Mesmo que um programador ´desavisado´ em determinado momento chame:
MeuObjeto.Free;
na próxima chamada de MeuObjeto ele estará lá novamente (uma nova instância, claro -- mas não haverá uma exceção de violação de acesso de memória)
Mas principalmente, função permite que o objeto seja criado APENAS quando for chamado pela primeira vez (e não na inicialização do programa, como ocorre com código da inicialization)
Outro ponto importante de notar é que a ´variável´ que contém a instância de nosso objeto fica em IMPLEMENTATION garantindo assim que nenhuma outra unit possa acessá-la diretamente (garantindo encapsulamento)
Ainda, a criação do método de classe ´Instance´ é opcional. Seu código poderia estar direto na função de entrada ´MeuObjeto´, caso não desejasse ter o método de classe. No exemplo acima:
TMeuObjeto.Instance.Nome := ´Teste´;
é igual a
MeuObjeto.Nome := ´Teste´;
Por fim, é importante notar que o destructor da classe foi re-escrito para destruir o objeto fLista criado no constructor, e que a seção finalization foi escrita para garantir que uma vez que InstanciaMeuObjeto tenha sido criado, seja destruído ao final da aplicação.
Vale salientar que este mesmo padrão pode ser implementado para Forms e DataModules (ou qualquer outra classe).
Vou ficando por aqui, esperando ter sido útil de alguma forma. Abraços a todos.
Anderson
Afarias
Posts
08/09/2009
Osocram
Não tenho o costume de usar o Initialization e o Finalization para instanciar ou destruir objetos, E sim para registrar Classes.
Mas assim que minha revista chegar, vou dar uma olhada no artigo p discutir melhor.
09/09/2009
Osocram
Recebi hj a minha revista, apenas com alguns dias de atraso.
Bom particularmente não gosto desse tipo de abordagem.
O que geralmente gosto, e estou tentando fazer nos sistema é que cada Objeto meu saiba se criar e se destruir.
Por exemplo meu sistema é MDI, mas as vezes tenho que usar alguns form SDI (não MDI) então qdo é assim eu criei uma classe no qual fiz uma ´Método de Classe´ geralmente .Execute; no qual faz o create do form e como é showmodal logo apos isso ele mesmo ja se destroi.
Ficando apenas assim a chamada do mesmo.
TMeuFormSDI.Execute;
Mas se for ver apenas estamos aplicando diferentemente os mesmos recursos que eles mostraram na materia.
Aquilo que colocaram deve ser usado com cautela. eu so vi uma aplicação para aquilo, até o momento, que seria para criar uma classe de usuario no sistema que ao logar eu guardaria todos os privilegios.
Mas nada impediria de eu criar isso no braço tbm usando um metodo Execute.
09/09/2009
Afarias
|recursos que eles mostraram na materia.
Não vejo bem por ai...
|Aquilo que colocaram deve ser usado com cautela.
Na minha modesta opnião, não deve ser usado de jeito nenhum. Além do problema conceitual, os códigos exemplo estão cheios de falhas como memory leaks, etc.
|eu so vi uma aplicação para aquilo, até o momento, que seria para criar
|uma classe de usuario no sistema que ao logar eu guardaria todos os
|privilegios.
Para isso servem os Singletons como no exemplo q mostrei.
A implementação de o singleton que dei de exemplo pode até não parecer muito diferente do código da matéria, mas tem detalhes q dão uma diferença muito grande se observados com cuidado -- tanto a nível conceitual quanto de implementação.
|Mas nada impediria de eu criar isso no braço tbm usando um metodo
|Execute.
Gosto desta abordagem e tb utilizo. Mas existem classes q são manipuladas, trocam informações, etc, onde esta abordagem não se aplica.
Neste caso que vc citou, vc cria um método de classe q encapsula uma ação completa -- criação da instancia, execução de uma tarefa e destruição!
Isto vai além da questão de inicialização de objetos (como uso de padrões singleton, factories, etc) -- e o método é específico para uma tarefa.
T+
10/09/2009
Wdrocha
E para que os colegas do fórum entendam melhor o q ele falow sobre o Singleton, ele é um padrão de projeto utilizado quando queremos apenas uma única instância de algum objeto.
Este é apenas um dos muitos padrões utilizados hj no mercado, existem mts outros, quem não conhece seria uma boa pesquisar e ler um pouco sobre Padrões de Projetos.
fica aew a dica...
flw
10/09/2009
Marco Salles
Afarias ,aonde vc ´viu´ memory Leaks nos códigos ???
10/09/2009
Marco Salles
Afarias ,aonde vc ´viu´ memory Leaks nos códigos ???
10/09/2009
Knight_of_wine
Inclusive utilizo uma classe de conexão Singleton muito boa que um amigo criou, assim posso usar minha conexão apenas quando necessito dela.
Isso aumentou a performance de um de meus sistemas em 45¬, algo incrível.
Achei muito massa a iniciativa de discutir um tópico da revista aqui.
10/09/2009
Afarias
Rocha disse tudo.
[quote:bfe68019b8=´Marco Salles´]
Afarias ,aonde vc ´viu´ memory Leaks nos códigos ???
[/quote:bfe68019b8]
1) Nas listagem 3 é criado um construtor para a classe que cria um objeto TStringList que NUNCA é liberado da memória pq não é criado um Destructor que teria esse papel. No texto inclusive é afirmado que o destructor não é necessário!! MAS É!
A não ser que vc utilize interfaces (ref-counted) ou um memory manager habilitado com um garbage collector os objetos criados não são destruídos automaticamente.
2) Nas listagem 5, exemplo com DM, ainda pior... na seção finalization o DataModule NÃO é destruído, apenas ´apontado´ para NIL!
finalization
DMTeste := nil;
Neste caso o ponteiro aponta para nil e a memória que era usada pelo objeto continua sendo utilizada... No texto é alegado que todos os DataModules de um projeto são destruidos ao com o témino da aplicação. Mas está incorreto...
São destruidos automaticamente apenas DataModules (assim como os Forms) criados tendo o objeto Application (ou outro qualquer que seja destruído em algum momento) como OWNER. Sendo que no código o Datamodule em questão NÃO tem um Owner.
DMTeste := TDMTeste.Create(nil);
Rsss.. Não achei outro espaço para isso... Achei q era aqui mesmo :wink:
T+
10/09/2009
Marco Salles
1) Nas listagem 3 é criado um construtor para a classe que cria um objeto TStringList que NUNCA é liberado da memória pq não é criado um Destructor que teria esse papel. No texto inclusive é afirmado que o destructor não é necessário!! MAS É!
A não ser que vc utilize interfaces (ref-counted) ou um memory manager habilitado com um garbage collector os objetos criados não são destruídos automaticamente.
2) Nas listagem 5, exemplo com DM, ainda pior... na seção finalization o DataModule NÃO é destruído, apenas ´apontado´ para NIL!
finalization
DMTeste := nil;
Neste caso o ponteiro aponta para nil e a memória que era usada pelo objeto continua sendo utilizada... No texto é alegado que todos os DataModules de um projeto são destruidos ao com o témino da aplicação. Mas está incorreto... [/quote:0c834bbb29]
Afarias , ja tinha percebido uma das falhas e tinha ate reportado o erro em um
email em particular para o autores e um deles gentilmente me respondeu
Como Resposta Obtive que a partir do DataModule foi INVENÇÃO do Pessoal
da Revista ..( Que estã precisando Aprender Delphi )
Agora gostaria de ser solidário aos Autores e isto não encaro como falta .
Errar todos nos erramos . Cometemos Erros e deslizes . Nos aprendemos muito
mais com os erros do que com os Acertos .
O que não podemos aqui em hipotese nenhuma é tomar este Artigo como
o Vilão da História . Vários são os Artigos que podemos considerar como
ruims e ate hj não tomou proporções como a que este esta tomando.
Gostaria de respeitar os autores , e se escrerem outro certamente eu os
lerei , mesmo que seja para critica-los ou não.
A Culpa no meu entender é a falta de um Intercambio mais eficiente entre a Revista e O Forum .
10/09/2009
Afarias
Veja, esta é uma revista TÉCNICA ao meu ver, e revistas técnicas (e PAGAS) devem apresentar matérias técnicas CORRETAMENTE ou não tem sentido.
Claro q falhas existem, mas tanto autores quanto principalmente os editores técnicos da revista deveriam estar mais atentos ou fica a impressão *no mínimo* de falta de atenção com o leitor.
Mas, voltando...
Meu objetivo com este tópico nem foi criticar -- isto eu fiz em e-mail enviado a REVISTA (não aos autores) q nunca foi respondido. Nem citei autores ou editores...
Meu meu tópico original apenas apresenta uma técnica em alternativa ao que fora colocado na matéria em questão -- na esperança que iniciantes desavisados fiquem atentos.
T+
10/09/2009
Weber
O artigo ´Objetos Auto-instanciáveis´ veio a existir a partir de uma discussão que tivemos sobre classes que criei para facilitar o trabalho da equipe de desenvolvimento, entre estas classes por exemplo tenho uma que chamo de TDBUpdate, os métodos da classe podem ser chamados a qualquer momento de qualquer lugar do sistema sem se preocupar se ela foi instanciada ou não.
Ao meu ver foi uma infelicidade o exemplo aplicado no artigo e não o artigo como um todo.
Vejo tudo como afarias já colocou, a classe deve ser instanciada quando existir realmente e necessidade e não no Initialization, no meu ponto de vista usando o Initialization não houve “auto-instancia”.
Veja abaixo parte de um código com “auto-instancia”
{ TDBUpdate } procedure TDBUpdate.CheckCreate; begin if not Assigned(DBUpdate) then DBUpdate := TDBUpdate.Create(nil); end; procedure TDBUpdate.TableCreate(Table: ShortString; Fields: array of ShortString); begin CheckCreate; ... end;
A conversa pode ir muito mais além, um colega meu certificado em java uma vez me disse que eu era louco que um código deste jamais poderia existir.
10/09/2009
Afarias
rssss... estou com esse seu colega :wink:
T+
10/09/2009
Knight_of_wine
Ninguém é dono da verdade, mas podemos sim contribuir para que o pessoal aprimore os artigos e melhorem cada vez mais o conteúdo que pagamos pra ter.
10/09/2009
Afarias
Na minha opinião, não poderia ter dito melhor.
T+
Clique aqui para fazer login e interagir na Comunidade :)