[quote=rmarin]Então suas vantagens 3 e 4 não são válidas, pois nem para os caras comparados você precisa do que foi mencionado.
E usando seu exemplo do Spring, na verdade ele é um contra-exemplo, pois por padrão os seus beans são Singletons, e nesse caso, você usou o tal framework.[/quote]
Apesar de eu ter citado o exemplo de um framework de IoC, o Singleton continua não precisando de dependências externas, o que continua sendo uma vantagem.
E, ele também não depende de reflexão. Nem é comum utiliza-la. Então, porque essas vantagens não são válidas? As duas ainda se aplicam. Acho que o fato de também se aplicarem para o IoC, pelo menos em seu caso mais simples, não invalida elas para o Singleton, como sua frase deu a entender.
Eu não estava comparando o Singleton ao IoC, coisa que você fez desde o primeiro post que eu fiz. Eu apresentei algumas vantagens e desvantagens que considero na hora de escolher um Singleton. No C++, você acaba tendo menos poder com IoC - justamente pela ausência da reflexão, e por não poder usar as ótimas técnicas de dependency injection com a mesma facilidade - e parte dos problemas encontrados no Java não se aplicam: não existem multiplos class loaders e, dependendo do tipo de aplicação, nem muitas threads.
E também não disse que IoC é complicado, nem que era obrigatório ter um framework de IoC para faze-lo. Na verdade, releia os meus posts e veja que em momento nenhum condenei o IoC, muito pelo contrário, digo que ele é util na maioria dos casos.
Mas também vejo muita gente aqui no GUJ simplesmente repetindo a cartilha, sem parar para analisar se o padrão aplica-se ou não para seu caso, ou simplesmente trocando por frameworks sem sequer parar para analisar o impacto que o uso de um software terceiro trará a seu projeto. Como eu falei desde o primeiro post, o importante não é condenar ou não o Singleton. Mas entender o seu funcionamento, seus problemas e ser capaz de analisar se, em dada situação, ele é adequado ou não, se existem alternativas melhores, etc.
E isso vai variar de acordo com o conhecimento da equipe, a linguagem utilizada, o problema a ser resolvido e uma série de outros fatores, que não poderão ser cobertos em nossos posts por aqui.
Você sabe, tão bem quanto eu, que isso não é IoC. Só o setter ainda não inverteu o controle de nada. Até porque, uma das implementações clássicas de IoC está no mecanismo de eventos, fazendo a inversão do controle numa interface gráfica, por exemplo. E nesse caso, não há nem construtores e nem setters.
Na verdade, frameworks usam IoC o tempo todo. Como o próprio nome diz, inversion of control, está na inversão no controle. Ou seja, está no fato de normalmente uma implementação A controlar B, e você modificar a solução para que B controle A. Callbacks também são uma forma de IoC. MVC é uma forma de se implementar IoC (ao invés de eu pegar os dados e desenhar um Table, eu deixo que o Table se desenhe e pergunte ao model a respeito dos dados). No C++, existe IoC implementado de outras formas, como através do uso de policies e multimétodos. O setter e o construtor a mais na classe é um mecanismo, para viabilizar o IoC no caso da dependency injection, não o IoC em si.
Também é bom lembrar que um setter sem sincronização terá os mesmos problemas de thread-safety que um Singleton sem sincronização. Se você precisar da garantia que o Singleton fornece (e se propõe a resolver), ou seja, se estiver controlando um recurso único, também terá a necessidade de preocupações de multiplos class loaders. E daí surgem os frameworks de IoC, que tentam cobrir esses fatores, além de fornecer outros serviços.
É fácil comparar os problemas do Singleton levando em consideração todos esses aspectos, e depois dizer que o IoC também é simples, mas daí desconsiderando thread-safety e a necessidade inicial: ter uma única instância, mesmo entre vários classloaders.
Não estou dizendo com isso que o Singleton é melhor que IoC. O chato de postar coisas como essa é que tenho que ficar me repetindo e dizendo que realmente há soluções melhores na maior parte dos casos.
De fato, existem três problemas que irritam profundamente ao se usar Singleton:
- Ele agrega uma responsabilidade a mais na classe: a de gerenciar sua construção. Essa baixa de coesão pode ser prejucial ao deixar a classe mais complexa;
- É menos flexível. O mecanismo de construção da classe fica enraizado num método estático. E métodos estáticos não podem ser sobrescritos, herdados, ou não há possíbilidades de substitui-los sem recompilação de todo o código que usa a classe.
- Ele é normalmente usado como substituto de uma variável global: E fazer isso é tentador e realmente é a forma errada de utiliza-lo. Por isso, antes de optar por um Singleton deve-se realmente ter certeza de que a necessidade de uma única instância realmente existe.