Composição ou não? Eis a questão

Amigos,

Há grandes diferenças conceituais entre as duas abordagens abaixo?

Abordagem1

[code]class Arquivo {

Registro registro;
...

public Arquivo() {

	registro = new Registro();
	...
}

public void MetodoA() {

	registro.fazAlgumaCoisa();
}

}
[/code]

Abordagem2

[code]class Arquivo {

public Arquivo() {
	...
}

public void MetodoA() {

	Registro registro = new Registro();

	registro.fazAlgumaCoisa();

}

}
[/code]

Poderiam ser citadas vantagens e desvantagens de cada uma das abordagens?

Tudo varia da sua necessidade.

Você precisa dessa referência ao registro no seu objeto? Faz sentido ele existir ali? Então use a abordagem 1

Agora, se ele for só algo que você precise pra um processamento específico em algum método, e depois não precisará mais dele, use a abordagem 2.

[quote=digaoneves]Tudo varia da sua necessidade.

Você precisa dessa referência ao registro no seu objeto? Faz sentido ele existir ali? Então use a abordagem 1

Agora, se ele for só algo que você precise pra um processamento específico em algum método, e depois não precisará mais dele, use a abordagem 2.[/quote]

Legal a sua mensagem.
Vamos supor que a situação concreta se encaixe mais no caso do processamento específico em algum método, conforme descrito por ti, em termos de eficiência, haveria alguma perda em se utilizar a abordagem 1?

então, em termos de performance, é uma referência a mais na memória, não vou dizer que vai dar lentidão por causa disso, mas se você nunca mais for usar aquele atributo, não tem por que ficar carregando ele pra lá e pra cá.

Está correto . andredf, o problema de se alocar referência que não será utilizada é se você usar isso como costume. Em pequenas aplicações ou até mesmo em exercícios de colégio/universidade, é aceitável, mas em sistemas de grande porte (portais, ERP) isso é um problema . Portanto, busque evitar esse tipo de implementação, em que instancia um objeto cuja referência pode simplesmente não ser utilizada.

Abraços.

Ok, amigos.
Com essas dicas, apesar de ter feito boa parte do programa utilizando a abordagem1, estou propenso a gastar algumas horas passando-o para a abordagem2.
Fica apenas uma dúvida, caso futuramente haja necessidade de utilizar o objeto do tipo Registro em mais de um método do tipo Arquivo, será fácil voltar à abordagem1?

Outra coisa, passar um Array considerado grande como argumento de um método, não causa problema de performance, já que o que é passado na verdade é a referência ao Array, estou certo?

[quote=andredf]Ok, amigos.
Com essas dicas, apesar de ter feito boa parte do programa utilizando a abordagem1, estou propenso a gastar algumas horas passando-o para a abordagem2.
Fica apenas uma dúvida, caso futuramente haja necessidade de utilizar o objeto do tipo Registro em mais de um método do tipo Arquivo, será fácil voltar à abordagem1?

Outra coisa, passar um Array considerado grande como argumento de um método, não causa problema de performance, já que o que é passado na verdade é a referência ao Array, estou certo?

[/quote]

O tamanho do objeto não altera em nada sua perfomance, o que altera é o que tu faz com esse objeto. Não tem problema alguma passar esse Array como parametro entre métodos. Sobre voltar a abordagem, sim, é relativamente simples. Veja, se você tem 5 métodos e em 4 usa o outro objeto, instanciar ele no construtor até faz sentido, porque a probabilidade de usar essa referência é significativamente alta, mas se tem os mesmos 5 e precisa dele em 2, porque fazer isso ? Por isso foi dito para estudar tua necessidade, assim, saberá como filtrar.

[quote=nel][quote=andredf]Ok, amigos.
Com essas dicas, apesar de ter feito boa parte do programa utilizando a abordagem1, estou propenso a gastar algumas horas passando-o para a abordagem2.
Fica apenas uma dúvida, caso futuramente haja necessidade de utilizar o objeto do tipo Registro em mais de um método do tipo Arquivo, será fácil voltar à abordagem1?

Outra coisa, passar um Array considerado grande como argumento de um método, não causa problema de performance, já que o que é passado na verdade é a referência ao Array, estou certo?

[/quote]

O tamanho do objeto não altera em nada sua perfomance, o que altera é o que tu faz com esse objeto. Não tem problema alguma passar esse Array como parametro entre métodos. Sobre voltar a abordagem, sim, é relativamente simples. Veja, se você tem 5 métodos e em 4 usa o outro objeto, instanciar ele no construtor até faz sentido, porque a probabilidade de usar essa referência é significativamente alta, mas se tem os mesmos 5 e precisa dele em 2, porque fazer isso ? Por isso foi dito para estudar tua necessidade, assim, saberá como filtrar.[/quote]

Ok, entendi.
Agora outra coisa, vamos supor que no metodoA() haja um loop (podendo se repetir por milhares de vezes) e em cada iteração, o objeto do tipo Registro será utilizado, porém tendo seus atributos internos com dados diferentes. Como seria feito um código eficiente?
Vou tentar melhor explicar via código.
Algo mais ou menos assim (eu não preciso guardar as informações de cada registro lido):

[code]class Arquivo {

public Arquivo() {   
    ...   
}   

public void MetodoA() {   

while (enquanto não for final do arquivo) {

	aqui executa método para ler próxima linha do arquivo

	Registro registro = new Registro();   

	registro.obtemDadosdaLinhadoArquivo();

	registro.fazAlgumaCoisa();   

	aqui deveria destruir o objeto registro???

} // final do while

}   

}
[/code]

É melhor, no início da cada iteração (logo após o while) criar um novo objeto do tipo Registro e antes do final do while destruir o objeto? Como?
Se não destruir o objeto, a memória poderá estar carregada de milhares de objetos do tipo Registro desnecessariamente?

Se o comando Registro registro = new Registro() for colocado antes do while, fica melhor?

Ou há alguma maneira melhor de fazer isso? Usando o padrão Singleton, por exemplo?

O pattern Singleton não é aconselhável por n motivos. Há exceções em que ele é utilizado, mas se deve ter muito cuidado. Se procurar aqui mesmo no GUJ, verá extensas discussões sobre este padrão. Nós usamos aqui, mas é via injeção do JEE 6 e é 100% controlado pela servidor de aplicação, que faz todo o gerenciamento da instância, bem diferente de você fazer isso na “mão”.

Sobre o loop, tu tem que parar e pensar cara. Veja, tu vai instanciar N registros só para poder invocar métodos dele ? Não né ?
Instancia uma única vez e usa. Quando é instanciando várias vezes ? Vamos supor que tu queira gravar informações em um arquivo e/ou banco de dados, mas essas informações podem ser diferentes para cada momento. Então, tu tem um objeto que vai gravar isso, no caso, o objeto Registro. Depois, tu vai iterar na lista de Registro e pegar item a item da lista para persistir em banco/arquivo, compreende ?

Para esse tipo de caso, não tem como fugir disso. E não se destrói um objeto, você até pode forçar o uso do GC, mas imagina forçar isso dentro de um loop !!! Sem falar que não há garantias que o GC vai ser “ativado” naquele momento. Portanto, tu precisa analisar tu necessidade, é difícil tu dar uma resposta a um exemplo genérico.

[quote=nel]O pattern Singleton não é aconselhável por n motivos. Há exceções em que ele é utilizado, mas se deve ter muito cuidado. Se procurar aqui mesmo no GUJ, verá extensas discussões sobre este padrão. Nós usamos aqui, mas é via injeção do JEE 6 e é 100% controlado pela servidor de aplicação, que faz todo o gerenciamento da instância, bem diferente de você fazer isso na “mão”.

Sobre o loop, tu tem que parar e pensar cara. Veja, tu vai instanciar N registros só para poder invocar métodos dele ? Não né ?
Instancia uma única vez e usa. Quando é instanciando várias vezes ? Vamos supor que tu queira gravar informações em um arquivo e/ou banco de dados, mas essas informações podem ser diferentes para cada momento. Então, tu tem um objeto que vai gravar isso, no caso, o objeto Registro. Depois, tu vai iterar na lista de Registro e pegar item a item da lista para persistir em banco/arquivo, compreende ?

Para esse tipo de caso, não tem como fugir disso. E não se destrói um objeto, você até pode forçar o uso do GC, mas imagina forçar isso dentro de um loop !!! Sem falar que não há garantias que o GC vai ser “ativado” naquele momento. Portanto, tu precisa analisar tu necessidade, é difícil tu dar uma resposta a um exemplo genérico.[/quote]

Então no exemplo que citei bastaria eu tirar o comando Registro registro = new Registro() de dentro do loop e colocá-lo antes do comando while?
Assim eu estaria utilizando sempre a mesma instância de registro?

[quote=andredf][quote=nel]O pattern Singleton não é aconselhável por n motivos. Há exceções em que ele é utilizado, mas se deve ter muito cuidado. Se procurar aqui mesmo no GUJ, verá extensas discussões sobre este padrão. Nós usamos aqui, mas é via injeção do JEE 6 e é 100% controlado pela servidor de aplicação, que faz todo o gerenciamento da instância, bem diferente de você fazer isso na “mão”.

Sobre o loop, tu tem que parar e pensar cara. Veja, tu vai instanciar N registros só para poder invocar métodos dele ? Não né ?
Instancia uma única vez e usa. Quando é instanciando várias vezes ? Vamos supor que tu queira gravar informações em um arquivo e/ou banco de dados, mas essas informações podem ser diferentes para cada momento. Então, tu tem um objeto que vai gravar isso, no caso, o objeto Registro. Depois, tu vai iterar na lista de Registro e pegar item a item da lista para persistir em banco/arquivo, compreende ?

Para esse tipo de caso, não tem como fugir disso. E não se destrói um objeto, você até pode forçar o uso do GC, mas imagina forçar isso dentro de um loop !!! Sem falar que não há garantias que o GC vai ser “ativado” naquele momento. Portanto, tu precisa analisar tu necessidade, é difícil tu dar uma resposta a um exemplo genérico.[/quote]

Então no exemplo que citei bastaria eu tirar o comando Registro registro = new Registro() de dentro do loop e colocá-lo antes do comando while?
Assim eu estaria utilizando sempre a mesma instância de registro?[/quote]

Se você precisa exclusivamente dos métodos desse objeto, claro. Instancia fora e apenas use a referência.