Singleton com mais instancias

com certeza! ja nao gosto de singleton, imagina singleton POG!! hahaha

mas achei mto legal a gambiarra dele… ja tive uns devaneios de como usar codigo parecido pra outras coisas :evil:

[quote=sergiotaborda]Realmente é uma imbecilidade dizer que Singleton é ruim. Como todos os padrões quando não são bem implementados ou não estão sendo usados corretamente tornam-se um problema. Mas isso não é erro do padrão isso é erro da aplicação do padrão. Então quando vc começar a pensar que o singleton tem problemas , provavelmente é vc que está com problemas ou o seu design.
Singleton é um padrão difícil de implementar e dependendo da aplicação existem necessidades especificas, e como tal se deixado nas mãos de um programador inexperiente pode dar problema depois. Mas o problema está no programador e no seu chefe e não no padrão.

Driblar o padrão com reflection é jogo baixo. Com reflection podemos driblar qualquer programa e causar qualquer tipo de dados. A única forma de evitar isso é usar um SecurityManager (Aliás o ppr artigo explica isso). Com um SecurityManager o setAcessible() não funciona.

Singleton é apenas um factory que retorna sempre a mesma instância. Vcs vão dizer que o factory é um padrão do mal ?!?

Singleton é um anti-pattern !!! Ai já foi demais … isso não é sério.[/quote]

Geralmente se usa Singleton e Factory em plataformas sem suporte “nativo” a Inversão de Controle\Injeção de Dependências (vide EJB 2, Struts 1.X “puro”).

Singleton é um jeito “mágico” de obter um objeto unico com classloader. É muito parecido com deixar uma classe com tudo static e chamar ela…

É muito melhor usar uma plataforma com suporte “nativo” a Inversão de Controle\Injeçãp de Dependências.

[quote=microfilo][quote=sergiotaborda]

Singleton é apenas um factory que retorna sempre a mesma instância. Vcs vão dizer que o factory é um padrão do mal ?!?

Singleton é um anti-pattern !!! Ai já foi demais … isso não é sério.[/quote]

Geralmente se usa Singleton e Factory em plataformas sem suporte “nativo” a Inversão de Controle\Injeção de Dependências (vide EJB 2, Struts 1.X “puro”).

Singleton é um jeito “mágico” de obter um objeto unico com classloader. É muito parecido com deixar uma classe com tudo static e chamar ela…

É muito melhor usar uma plataforma com suporte “nativo” a Inversão de Controle\Injeçãp de Dependências.[/quote]

Isso é uma forma de esconder o problema. Se voce for ver esse “codigo nativo que suporta IoC” verá que ele usa factories e portanto ele pode decidir tornar objetos singleton. O Spring faz exatamente isso. A diferença é que ele usa uma Map em vez de uma variável explicita e portanto controla o numero de instâncias explicitamente. Mas ninguém disse que um Singleton não podia usar Map.

Injeção de Dependência não elimina o problema porque o próprio injector é um singleton. Se ele não é, o objeto de onde le as configurações é.

Para quem acha que injecção é a solução; arranje uma forma de Injeção para criar System sem usar singleton - mas que mantenhas as mesmas carateristicas - e depois falamos.

Ah! e o padrão Registry é uma especialização de Singleton, por isso tb não evita o uso de Singleton.

E o singleton não tem que ser único só por classloader ele pode ter que ser único numa applicação destribuida inteira.

É melhor usar um framework de Injeção ?! … tlv, mas sem singleton esse framework não existiria.

Olhe os argumentos dos artigos e links e vai ver que ninguem condena Singletons para seu uso real (ver GOF). O container de IoC nao precisa ser singleton, de onde voce tirou isso? O Spring usa singletons por padrao (eh soh dizer que nao quer que o bean seja singleton) porque se baseia em componentes sem estado, nao faz sentido criar isntancias novas se apenas uma pode ser utilizada. Eh exatamente o mesmo conceito de Servlets e Servlets com SingleThreadModel e ainda assim um servlet nao eh um singleto ja que nada impede que haja mais de uma instancia.

Nao eh porque voce tem um repositorio centrazliado de objetos que ele eh um singleton, por favor releia (ou leia…) a descricao do padrao antes de falar este tipo de coisa.\

Registry eh especializacao do Singleton? Meu Zahl, de onde veio isso?
Singleton eh um objeto que soh pode ser isntanciado uma (ou N) vez(es), nao um lugar onde se guardam objetos. Registries guardam objetos e nada impede que haja mais de um registry, desde que voce saiba como acessa-los (a arquitetura do memcached eh um exemplo).

Quanto ao singleton ser unico para todo um sistema distribuido, isso eh bem relativo. Pode ser que sim, pode ser que nao, depende da necessidade, muitas vezes voce quer um unico objeto por classloader, por JVM ou mesmo por modulo do sistema.

Sergio, considere esse seu ultimo aviso: ou voce trata as pessoas com respeito minimo que se espera de alguem ou suas mensagens serao apagadas sem do nem piedade.

Me mostra esse SingletonMap então O.o

Me mostra esse DistributableSingleton então :stuck_out_tongue:

[quote]
É melhor usar um framework de Injeção ?! … tlv, mas sem singleton esse framework não existiria.[/quote]
Quem disse?

O que eu quis dizer lá em cima é que se é tão absurdamente propenso fazer do singleton um uso errado, devemos certamente pensar em maneiras de não utiliza-lo nunca.

É o caso dos ponteiros, por exemplo… ninguém questiona a utilidade deles e todos sabem que basta serem usados corretamente. Mas ninguém sentiu saudades quando o Java criou uma forma melhor e se livrou deles… isso porque, apesar de bons, era tão difícil “aplica-los corretamente” que foi melhor criar uma maneira definitiva de elimina-los.

Definitivamente, se só especialistas em modelagem sabem usar o singleton de maneira correta, é melhor mesmo pensarmos em uma solução mais natural, que contemple nossos nossos momentos preguiçosos e descuidados ou aquele funcionário que não manja tanto assim…

[quote=pcalcado]

Sergio, considere esse seu ultimo aviso: ou voce trata as pessoas com respeito minimo que se espera de alguem ou suas mensagens serao apagadas sem do nem piedade.[/quote]

Onde é que naquela frase eu desrespeitei alguém ?!

Se ninguém condena os singletons no seu uso real o que vêm a ser certas mensagem deste tópico como “singleton=anti-pattern” e “Ja nao basta a bizarrice do Singleton existir(…)” e " Singletons são estúpidos!" ??
Concerteza não são afirmações em prol do uso real (aliás o unico que existe) dos singletons e sim contra ele.
Mas pronto, se essas afirmações não são contra o uso de singletons, fim de conversa e este tópico não tem sentido.

[quote=microfilo][quote=sergiotaborda]
Isso é uma forma de esconder o problema. Se voce for ver esse “codigo nativo que suporta IoC” verá que ele usa factories e portanto ele pode decidir tornar objetos singleton. O Spring faz exatamente isso. A diferença é que ele usa uma Map em vez de uma variável explicita e portanto controla o numero de instâncias explicitamente. Mas ninguém disse que um Singleton não podia usar Map.
[/quote]
Me mostra esse SingletonMap então O.o

Me mostra esse DistributableSingleton então :stuck_out_tongue:
[/quote]

É so vc me mostrar onde eu falei de SingletonMap e DistributableSingleton.
Mas se vc leu os links deixados neste tópico, concerteza conhece o segundo e se vc conhece a classe Collections vc conhece o primeiro - embora eu não estivesse falando de um mapa singleton e sim de um singleton que usa um mapa internamente em vez de uma variável de tipo especifico.

[quote]

[quote]
É melhor usar um framework de Injeção ?! … tlv, mas sem singleton esse framework não existiria.[/quote]
Quem disse?[/quote]

Quem disse que não ?

“A Registry is essentially a global object, or at least it looks like one - even if it isn’t as global as it may appear” - http://www.martinfowler.com/eaaCatalog/registry.html

Quantos registry ha ? Um. Portanto é um caso especial de singleton. É especial pq não obdece ao padrão normal de Singleton.getInstance(), mas da mesma forma só existe um.

[quote=sergiotaborda]
“A Registry is essentially a global object, or at least it looks like one - even if it isn’t as global as it may appear” - http://www.martinfowler.com/eaaCatalog/registry.html

Quantos registry ha ? Um. Portanto é um caso especial de singleton. É especial pq não obdece ao padrão normal de Singleton.getInstance(), mas da mesma forma só existe um.[/quote]

1 - Nao senhor. Global nao quer dizer que ha apenas um, quer dizer que esta disponivel globalmente. Um objeto definido como variavel global em C++ nao eh um singleton, por exemplo.

Nao invente o qu nao esta escrito, leia a definicao:

http://www.google.com.br/search?hl=pt-BR&q=define%3Aglobal&meta=

2 - NADA impede que voce tenha mais de um registry

[quote=pcalcado]

1 - Nao senhor. Global nao quer dizer que ha apenas um, quer dizer que esta disponivel globalmente. Um objeto definido como variavel global em C++ nao eh um singleton, por exemplo.

Nao invente o qu nao esta escrito, leia a definicao:

http://www.google.com.br/search?hl=pt-BR&q=define%3Aglobal&meta=

2 - NADA impede que voce tenha mais de um registry[/quote]

Então vejamos…
O padrão registry não cria uma objeto Registry, por isso não tem como ter dois. O registry é uma classe em que os métodos são todos estáticos. O estado é encapsulado e a unica coisa que se vê são os métodos. Exemplo :


public abstract class Registry {

     private Registry (){}

     private static Map map = new HashMap();

     public static void registerService(Service service){
            map.put(service.getClass(), service);
      }

      public static Service getService(Class service){
            return (Service) map.get(service.getClass());
      }

}

Isto é usado assim :

Registry.registerService(new LoggingService());

LoggingService service = (LoggingService)Register.getService(LoggingService.class)

Em qualquer ponto do codigo vc pode fazer estas chamadas e elas sempre funcionarão.É isto que significa ser global. Como o seu link mesmo explica
"Pertaining to information available to more than one program or subroutine. "

O objeto retornado é o mesmo que registrado. Com isto eu ganho o mesmo efeito que um Singleton (unica instancia, acesso global) sem ter que usar o Singleton.getInstance(). Mas se tomar atenção verá que o Registry na realidade permite vários singletons. Tudo depende da implementação do Registry e poderia implementa um registry de factories que retorna N objetos.

Como Registry é abstract vc não conseguirá criar nenhuma instancia dele e como tem construtor privado não conseguirá herdá-lo para criar depois instancias. Por isso Registry é uma especialização de Singleton.
Mesmo que conseguisse herdá-lo como seus métodos são estáticos de nada adiantaria. Se isto não impede ter mais do que um registry então por favor escreva um código onde vc cria várias instâncias daquela classe Registry.

Global não quer dizer que ha apenas um ? Teoricamente não, mas tecnicamente sim. Suponha que vc tem 2 objetos Registry x e y (isto supondo que vc os consegue criar ) ora como eu executo o método em cima de x ? Por favor escreva um codigo demonstrado que vc consegue trabalhar com 2 objectos globais simultaneamente SEM usar singleton ou outro registry. … … … a solução simples é criar um Map numa classe qualquer e coloca x e y lá assim :


public class Auxiliar {

  public static Map mapa = HashMap();

  

}


// uso 


Auxlilar.mapa.put("x" , x) ; 
Auxlilar.mapa.put("y" , y) ; 

e depois 

Registry y = (Registry)Auxlilar.mapa.put("y") ; 

Ora, mas esse Auxiliar tem um mapa que é um objeto global. Então para poder dois registry globais eu tenho que ter 1 único mapa global. Não tem outra forma de fazer isto, vc é obrigado a ter um objecto global único em algum ponto do design. Mas vc é livre de criar uma classe que possibilite
trabalhar como vários objetos globais SEM usar um objeto global para ter acesso a eles. Fico à espera…

Supondo que vc consegue fazer isso, pense na utilidade de ter dois registros globais. Se eu registro todos os meus serviços no x , por exemplo, para quê eu preciso do y ? O objetivo de ser global é intrinsecamente que seja único porque não ha utilidade em ser global e multiplo.

Relativamente a IoC. Imagine que vc está usando uma das BeanFactories do Spring. Nada o impede de criar duas instancias da mesma fábrica, pois elas não são Singleton nem Registry. Usemos da XMLBeanFactory , podemos até pensar que será usado o mesmo arquivo xml de configuração para as duas. Nesse arquivo definimos um bean para ser singleton. Ele é realmente singleton ?
Não, porque cada instancia do factory terá o seu. Portanto IoC sozinho não garante que existirá 1 e apenas 1 objeto daquela classe de bean. Para vc garantir isso tem que criar um Registry ou um Singleton que garante que apenas um Factory daquele bean poderá ser construida. Obviamente que ninguem é louco de criar 2 factories para os mesmos beans, da mesma forma que ninguem é louco de driblar um singleton via reflection (até pq não teria qualquer efeito no sistema. as classes normais continuariam chamado Singleton.getInstance e obtendo sempre o mesmo objeto, não vendo nunca que existem mais. ) Mas o fato de ninguem ser louco para usar isso, não significa que não possa. Ora o objetivo do Singleton é impedir que possa! E ai que está o seu poder.
Para começar o singleton tem que ser final e ter constutor privado. Se alguma destas é falsa já não é um singleton. Tem que haver uma forma de obter o objeto , mas não implica que seja sempre o mesmo objeto a ser retornado. Por exemplo, o singleton pode ser implementado com weakreference e quando ninguem está usado ele simplesmente desaparece sendo criado quando voltar a ser necessário. O que o padrão tem que garantir é que ao longo do programa o resto da aplicação vê 1 e apenas 1 objeto daquela classe. Mesmo usando reflection para criar vários objetos da classe vc não tem como enganar a aplicação a usar elas todas, a mesmo que force isso, e ai a sua classe deixa de ser a implementação do padrão Singleton.

Como vimos IoC por si mesma não substitui o padrão Singleton. Registry tb não embora possa ser usado como um ele não garante a unicidade. Nenhum outro padrão resolve sem ser o Singleton e isto deveria ser obvio desde um inicio pois se ele não fosse a unica solução ele não seria um padrão para começo de conversa)

Alguém pode me dizer uma coisa, pq todo thread tem que virar um flame apaixonado?

Isso tá quase parecendo SCO vs IBM!
:mrgreen:

[quote=sergiotaborda]Não tem outra forma de fazer isto, vc é obrigado a ter um objecto global único em algum ponto do design. Mas vc é livre de criar uma classe que possibilite
trabalhar como vários objetos globais SEM usar um objeto global para ter acesso a eles. Fico à espera…[/quote]
Eu entendi o seu ponto, mas existe sim essa forma. Você não precisa criar um jeito estático de acessar o seu objeto único. Tem só um conflito de conceitos bem comum aqui.

Se você expõe um jeito global de acessar o seu objeto é porque os outros objetos estão precisando ir atrás daquilo que precisam. A IoC (ou antes que alguém me xingue, a DIP) diz para você fazer exatamente o contrário: em vez dos seus objetos saírem atrás de tudo que precisam para fazer o trabalho, o que eles precisam será fornecido, como dependências.

Dessa forma você não precisa de um acesso global. Só vai propagando o que precisa ser propagado. Ex. (tosco):

// Eu editei e mudei essa linha, senao tenho certeza que você ia dizer que container era singleton... // SuperObjeto singleNaoTon = container.meDaObjetoNovo(); SuperObjeto singleNaoTon = new SuperObjeto(); ComponenteUm comp1 = new ComponenteUm(singleNaoTon); comp1.servico(); e:

public class ComponenteUm { private SuperObjeto dependencia; public ComponenteUm(SuperObjeto dependencia) { this.dependencia = dependencia; } public void servico() { new ComponenteDois(dependencia).ajuda(); new ComponenteTres().termina(dependencia); } }

O exemplo é horrível, o importante é perceber o baixo acoplamento e a divisão de responsabilidades, já que cada objeto faz aquilo que foi criado para fazer e não tem que se preocupar de onde (ou qual método estático em que lugar global) pegar o que precisa.

[quote=Fabio Kung][quote=sergiotaborda]Não tem outra forma de fazer isto, vc é obrigado a ter um objecto global único em algum ponto do design. Mas vc é livre de criar uma classe que possibilite
trabalhar como vários objetos globais SEM usar um objeto global para ter acesso a eles. Fico à espera…[/quote]
Eu entendi o seu ponto, mas existe sim essa forma. Você não precisa criar um jeito estático de acessar o seu objeto único. Tem só um conflito de conceitos bem comum aqui.

Se você expõe um jeito global de acessar o seu objeto é porque os outros objetos estão precisando ir atrás daquilo que precisam. A IoC (ou antes que alguém me xingue, a DIP) diz para você fazer exatamente o contrário: em vez dos seus objetos saírem atrás de tudo que precisam para fazer o trabalho, o que eles precisam será fornecido, como dependências.
[/quote]

O DIP não resolve o problema que o Singleton se propõe resolver.
Mesmo com um injector que use sempre o mesmo objecto durante a injecção isso não garante que existe apenas esse objecto.
Eu posso criar outro injector ou eu posso criar o bean na mão e fazer a injeção na mão. Nenhuma destas opções garanteque exista apenas uma instância da classe. A única forma de garantir que existe 1 e 1 só objeto de uma certa classe é com o padrão Singleton.

As questões são:
1)O Singleton implica em usar objetos declarados estáticamente na classe ? Não. Essa é apenas a implementação mais simples e comum do padrão. Vc poderia usar, por exemplo, JNDI e manter o objeto lá.

  1. O Singleton implica em usar objectos globais ?
    Sim. Mesmo usando JNDI vc está usando objectos globais. Aliás esse é o ppr conceito do JNDI. Se vc usar so os atributos estáticos da mesma forma será um objecto global. se usar Regestry pra mascarar o singleton, da mesma forma será um objeto global. Nâo existe uma forma de garantir unicidade sem objeto global. Se vc usar um factory DIP vc só garante unicidade se o factory, ele mesmo, for global.

  2. IoC ou DIP subtituem Singleton ?
    Não. E espero já estar claro pq.

  3. Singleton é um padrão ruim?
    Não. Implementações menos cuidadas de singleton é que podem ser ruins.

  4. Criar instancias da classe que é supostamente um singleton usando reflection é uma violação do padrão singleton ?
    Não. Porque vc só consegue fazer isso se a implementação de singleton deixar. Basta que o Singleton force o uso de um SecurityManager para que isso não aconteça. É tudo uma questão de implementação.

  5. implementar um Singleton absoluto é dificil ?
    Sim. Muito dificil. Por isso as implementações de singleton se limitam a respeitar os requisitos do sistema que as vai usar e pronto.

  6. Registry subtitui Singleton ?
    Não. Registry mantém um estado de forma única e global (embora privada). Ou seja, o estado do Registry é um singleton.
    Mas ao encapsular o estado do Registry dentro da própria classe, não tem mais que implementar singleton explicitamente. Registry não subtitui singleton porque ele mesmo usa esse padrão internamente. Acontece apenas que a implmentação do singleton é mais simples nesse caso especifico.

  7. Ioc , DIP e Registry podem ser alternativas ao uso de singleton ?
    sim. Em casos simples em que não existe uma real necessidade de um único objeto da classe por vez , eles podem ser usado. Ou seja, vc pode usar IoC , DIP e Registry se o seu objetivo é poupar o sistema de criar N objetos iguais quando 1 só chega. Mas deixa de ser alternativa no momento que é necessário garantir que só um pode ser criado.

Repare como sublinhei sempre garantir. Isto porque essa é a palavra chave do padrão singleton.

Vc levantou o problema de que a necessidade de usar singleton advem de não está usando DIP. Isso não é correto. Imagine uma classe onde eu injeto um serviço que usa recursos nativos e faz um processamento pesado que só pode ser usado em thread única. O serviço é responsável por sincronizar os pedidos de várias threads e enviar para o codigo nativo. Para garantir que ninguem cria duas instancias deste serviço (o que causaria problemas com o codigo nativo que só aceita um processo de cada vez) eu tenho que usar Singleton para implementar esse serviço. Depois no framework de inversão eu tenho que dizer que aquele bean não usa new e sim um método de factory. Repare que tenho que garantir que existe apenas um serviço mesmo antes de pensar em usar DIP e a garantia tem que existir mesmo se não usar DIP. Portanto DIP não resolve o problema.

[quote=qmx]Alguém pode me dizer uma coisa, pq todo thread tem que virar um flame apaixonado?

Isso tá quase parecendo SCO vs IBM!
:mrgreen:[/quote]

Porque é esse, infelizmente, o principal efeito colateral dos trolls. Coloca todo mundo na defensiva e o negócio se desvirtua num bate-boca cujo único propósito é triunfar sobre o outro.

Não não. O que eu critiquei foi o fato de ter um meio estático-global de acessar a sua única instância. O que eu critiquei foi o fato de você precisar expor esse meio global de acesso.

Se os seus objetos/componentes apenas declaram a dependência a um outro objeto, pouco os importa se a instância é única ou não. Um objeto deve se preocupar em prestar os serviços para os quais foi criado, eventualmente com a cooperação de outros objetos. Não ter que controlar o ciclo de vida de outros objetos.

Não estou condenando a necessidade de existência de instancias únicas. Realmente há aplicações onde são necessárias. O que estou condenando é quem depende dessa instância única precisar saber como ter a tal instância única, ou mesmo ter de saber que ela é única. Percebe o alto acoplamento? Seja por jndi, seja por um factory method estático com construtor privado, seja por uma factory, seja por um builder, seja de um registry.

Aliás, se você realmente precisar pegar coisas de um container ou de um registry, injete o registry ou o container em vez de fazer Registry.getService(MeuServico.class).

Exemplo: componentes compartilhando o mesmo servico que faz operação demorada e sincroniza diversas chamadas a procedimentos nativos.

public class Componente { public Resultado metodoUtil() { MeuServico servico = Registry.getService(MeuServico.class); return servico.trabalha(); } }
Será que consigo testar os Componentes isoladamente? Não. Assim que eu tentar chamar o metodoUtil em qualquer um deles, vou estar testando o servico.trabalha() também. MUITO difícil de testar isoladamente e altíssimo acoplamento.

E assim?

[code]public class Componente {
private MeuServico servico;
public Componente(MeuServico servico) {
this.servico = servico;
}
public Resultado metodoUtil() {
return this.servico.trabalha();
}
}

MeuServico unicoServico = new MeuServico();
Componente um = new Componente(unicoServico);
Componente dois = new Componente(unicoServico);
um.metodoUtil();
dois.metodoUtil();[/code]

E então? Todos os componentes usam a mesma única instância de MeuServico? Precisei de um jeito estático-global para acessá-la? O segredo é fazer com que os objetos não precisem ir atrás de suas dependências.

E se eu quiser testar os Componentes isoladamente?

public class ComponenteTest extends TestCase { public void testMetodoUtilUsaMeuServico() { MeuServicoMock servico = new MeuServicoMock(); Componente componente = new Componente(servico); componente.metodoUtil(); assertTrue(servico.trabalhou()); } }
Mas aí você me pergunta:

Tem seu fundo de razão. Mas por que alguém iria querer criar um novo MeuServico, se todo mundo recebe como dependência?

Tirar a responsabilidade do Componente saber como o ciclo de vida do serviço funciona, diminui o acoplamento, aumenta a testabilidade e permite que você troque o funcionamento do cliclo de vida do MeuServico sem afetar ninguém. Pode ser que a instância deva ser única hoje, amanhã você decidiu que era melhor fazer um pool; o impacto da mudança será nulo. Pegou a idéia?

Sim. o código dentro de métodoUtil.
Ai vc deu a volta e deixou como

MeuServico unicoServico = new MeuServico();
 Componente um = new Componente(unicoServico);
 Componente dois = new Componente(unicoServico);
 um.metodoUtil();
 dois.metodoUtil();

na realidade , para manter a coerencia, deveria ser

MeuServico unicoServico =  Registry.getService(MeuServico.class);
 Componente um = new Componente(unicoServico);
 Componente dois = new Componente(unicoServico);
 um.metodoUtil();
 dois.metodoUtil();

ups… vc acabou de demonstrar que ao tirar o codigo de dentro de Componente vc teve que o colocar em outro lugar. E não tem outro jeito. O desafio é saber onde o colocar. Eu so estou dizendo que não ha como eliminar aquela chamada Registry.getService(MeuServico.class); independentemente de onde ela estiver.

Inversão de controle é muito bonito, mas alguem tem que continuar controlando. É apenas uma alteração de quem controla. O objecto que usa o serviço ou o objeto que cria o usuário do serviço. Mas não muda o fato de como obter o serviço. Vc pode encapsular o código de chamada ao registro da forma que quiser. Com dip ou sem dip , em algum lugar do codigo vc vai ter que usar o acesso global do registry. Você pode esconder isso. Mas o problema não é esse.
Eu entendo o seu ponto e eu o uso. A API publica não mostra objetos globais, eles são usados internamente. Tudo bem com isso. O ponto da questão é que eles existem e têm que existir e não ha como evitar a necessidade de usar objetos globais e unicos.

Bom, então como fazer para que o código de teste não vá atrás do Registry para injectar no Componente ? como fazer para que nunca seja necessário nenhum codigo invocar Registry.getService(MeuServico.class) ?
Em algum ponto vc vai ter que escrever aquele código. Pode ser nos testes , pode ser no codigo interno da API , no classloader , como AOP sem AOP , pode até ser o usuário da API a ter que o escrever. Onde vc vai escrever muda a qualidade da sua API, mas não muda o fato que alguem vai ter que escrever. Aquele código vai ter que ser executado em algum ponto. Certo ?

Uma API de boa qualidade vc não vê os objectos globais. A API os esconde, disfarça , encapsula. É bom que haja encapsulamento. Mas é bom também que não se perca de vista que o objeto global existe e continua lá.
E só isso. Para criar softwares precisamos de variáveis globais. Podemos não saber que elas estão lá, ou sequer ter que as manipular, mas estamos usando-as. Vc mesmo concordou com isso. Então acho que é claro, aceitável e pacifico o ponto que venho defendendo de que DIP/IoC não substitui Singleton e que dizer que Singleton é ruim ou que não precisamos dele porque podemos usar IoC é um argumento desprovido de razão.

Pela mesma razão que alguém tentaria driblar um singleton com reflection… tem gente que não tem nada que fazer … :wink:

(Veja com atenção o código que vc escreveu : nem todo o mundo tem como receber como dependência e ai é que está o ponto. O codigo de teste não o recebe como dependência, ele tem que usar o registro explicitamente)

E o que isso tem a ver com um singleton? Voce esta deturpando abertamento conceitos para se fazer verdade.

Leia o Gof e veja que o Singleton eh um objeto que pode ser instanciado N vezes (onde N geralmente é igual a um). Nada, repito: nada impede que eu tenha duas instâncias de registries. Se isto é útil ou não é outra coisa, dependente do contexto.

Além do mais, Registry é o padrão por traz de JNDI. Se sua afirmação anterior fosse verdade deveria haver apenas uma arvore JNDI num sistema distribuido, acho desnecessario reafirmar que isso nao eh verdade.

Voce esta inferindo coisas baseado em opiniao, nao em logica.

Quem disse que devemos retornar o mesmo objeto instanciado? O Regsitry pode ser passado como outro objeto. Eu posso muito bem criar uma instancia nova de registry a cada chamada, possivlemente copiando as entradas de uma chamada original. por que isso nao eh um registry?

E qual o problema de ter varios registries, com servicos diferentes, num sistema? talvez com serviços iguais, se for util! Leia o GOF: singletons nao podem ter mais de N isntancias. Registries podem, se isso eh util depende do contexto, o que interessa eh que nao sao nem de longe a mesma coisa.

NAO EXISTEM VARIOS SINGLETONS!

Singleton tem N instancias, se ele possui mais que isso nao eh singleton, se nao ha controle sobre o numero de instancias (como quando acontece com o registry) nao eh um singleton.

E quem disse, alem de voce, que é abstrato?

Sua afirmacoes nao possuem logica com a bibliografia atual. Se voce confirmar que trata-se de sua opiniao. Muito bem, voce tem o direito de defender esta, mas nao eh a opiniao de todos (pelo contrario!) e vai contra a bibliografia de referencia e… bem… contra o dicionario!

Onde, pelo amor de Zahl, os metodos de um registry sao estaticos? Quem afirmou isso além de você? Qual a jsutificativa? Quantos métodos de JNDI são estáticos?

Um objeto global quer dizer disponivel globalmente, nao é uma variavel global.

De qualquer forma, ainda que quisesse, cada registry pode ter sua propria forma de ser obtido (nao eh um singleton mesmo, cada forma retorna um objeto diferente) .

PODE PRECISAR, tudo depende do contexto. Voce nao pode afirmar que eu preciso ou nao, voce nao conhece os requisitos do sistema.

“Intrinsicamente unico” só porque voce quer. Dê uma olhada em qualquer programa em C que utilize variaveis globais e reafirme o que acabou de dizer.

Novamente: GLOBAL QUER DIZER ACESSIVEL GLOBALMENTE, NAO UNICO. Singleton eh um padrao que indica uma limitacao no numero do objetos existentes, geralmente apenas um.

Só se adotarmos sua definição de Singleton. Para as definições do mundo real um Singleton é escopado, ou seja: pode ser unico em um classloadres, em uma JVM, em um servidor, etc.

E não se propõe a ser. peloamordeZahl, preste antençao no debate antes de respoder.

Nao sei de onde voce eh mas as pessoas por aqui usam Singletons como variaveis globais, um comportamento que pode ser substituido por diversas tecnicas, entre elas IoC. Aprenda o cotenxto antes de entrar num debate!

Ah, agora um Registry pode ser um singleton, antes ele era um Singleton. Voce pode se decidir, por favor?

A pergunta é: resolve o que?

Ah, e quer dizer que o padrao eh a unica solucao para uma coisa? Na boa, de onde voce tira essas coisas? Dos livros eu sei que nao sao.

Recomendo fortemente que:

  1. leia os livros sobre padroes de projetos (Fowler e GOF, ao menos)
  2. procure um bom dicionario
  3. Escreva seu proprio livro/paper/artigo com suas ideias que sao completamente contrarias aos livros do item (1)

Acho que até o ponto ninguém mais discorda que a Injeção de dependência pode ou não ser usada, mas não substitui o uso de Registry ou Singleton. Acho que estamos sendo preciosistas e essa discussão não vai a lugar nenhum.
Não me importo se os métodos do Registry são estáticos ou não, se existe uma instância… que seja… não faz diferença. A questão de o Singleton ser único ou não, isso não me importa. Eu preciso de alguma coisa que me auxilie para guardar estado e não obrigue o sistema a refazer o mesmo trabalho diversas vezes, principalmente em uma realidade multithreading sobre a qual eu não tenha controle das chamadas (por exemplo, mdb, servlet, etc). Eu não tenho como injetar a dependência, de forma que tenho que recuperá-la de algum lugar. JNDI, Registry, Singleton… não me importa. A questão é que normalmente Singleton é fácil de implementar e resolve o problema.
Quanto à questão do acoplamento, qual é a diferença? Eu nunca vou mudar o jeito de trazer a instância e o resto não muda em nada. Com o registry não acontece exatamente a mesma coisa? Com a diferença, ainda, que eu tenho que conhecer a implementação do Registry E ainda por cima saber a chave para buscar o objeto que eu preciso. same f… thing.
Tudo bem, digam que é um lixo, mas dêem uma alternativa melhor e que seja realmente diferente em termos práticos. P.S.: Alguém algum dia precisou extender um singleton? Pode me explicar em que situação? Será que não estamos dourando a pílula sobre uma questão irrelevante? Será que o cara que escreveu singleton=Anti-pattern sabia do que estava falando ou simplesmente reproduziu o que alguém disse?

Abraço,

Armando

[quote=armando]Acho que até o ponto ninguém mais discorda que a Injeção de dependência pode ou não ser usada, mas não substitui o uso de Registry ou Singleton.
[/quote]

Substitui quando o Singleton é mal utilizado, que é em 99% dos casos. Muito dificilmente se tem motivos para ter um Singleton num sistema.

Simplesmente porque você não quer um Singleton, quer uma variável global. Podemos parar de chamar isso de Singleton já que não segue o padrão.

Ué, e qual o problema de usar IoC neste caso? “Uma realidade multithreading” é caso comum em aplicações J2EE e isso nunca foi problema.

Novamente: não é um singleton, é uma variável global.

Que tal testabilidade, para começar?

Tem por quê? Você pode abstrair o Registry usando uma Fcatory que retorna interface.

É rui, não? Use IoC então, ora bolas.

Já foi dada e você não explicou porque não poderia utilizar.

Já precisei mas nunca estendi porque não é viável, sempre joguei fora e reescrevi o códigod e acesso. Dê manutenção um tempo num sistema de gente grande que use esta ‘técnica’ de variáveis globais e você vai precisar. Ah, mas é claro que geralmente você pode evitar isso escrevendo outro singleton que é 99% igual ao primeiro.

De uma vez por todas:

  1. Singleton é um padrão que permite que hajam apenas uma ou N instâncias de um dado objeto. Se esta instância é obtida por um método (Factory methdo) estático isso não importa para o Singleton.

  2. Utilizar um variável estática para guardar um objeto que é obtido por outros por um método estático não é um Singleton (ao menos não precisa ter) -é um Factory Method estático- e é uma péssima prática desde os tempos das linguagens procedurais (ver Yourdon, Page-Jones e etc.)

  3. Em 99% dos casos pseudo-Singletons são utilizados para implementar o item (2)

  4. IoC e Registry não substituem (1) -nem se propoem a isso- mas substituem plenamente (2) e são altamente recomendados neste caso.