Pergunta

Vamos enfrentá-lo. O padrão Singleton é tópico altamente controverso com os programadores hordas em ambos os lados da cerca. Existem aqueles que sentem como o Singleton é nada mais do que uma variável global glorificado, e outros que juram por padrão e usá-lo incessantemente. Eu não quero o Singleton Controvérsia a mentira no coração da minha pergunta, no entanto. Todos podem ter um cabo-de-guerra e batalha para fora e ver quem ganha para todos os cuidados de I . O que eu estou tentando dizer é, eu não acredito que há uma única resposta correta e eu não estou tentando intencionalmente inflamar disputas partidárias. Estou simplesmente interessado em únicas-alternatives quando faço a pergunta:

são suas alternativas específicas para o padrão GOF Singleton?

Por exemplo, muitas vezes quando eu usei o padrão Singleton no passado, estou simplesmente interessados ??em preservar o estado / valores de uma ou várias variáveis. O estado / valores das variáveis, no entanto, pode ser mantida entre cada instanciação da classe usando variáveis ??estáticas em vez de usar o padrão Singleton.

O que outros a idéia de que você tem?

EDIT: "como usar o singleton corretamente" Eu realmente não quero que este seja outro post sobre Novamente, eu estou procurando maneiras de evitá-lo. Para se divertir, ok? Eu acho que eu estou pedindo uma questão puramente acadêmica em sua melhor voz trailer do filme, "Em um universo paralelo onde não há Singleton, o que poderíamos fazer?"

Foi útil?

Solução

Alex Miller em " Padrões Eu Odeio " aspas o seguinte:

"Quando um solteirão parece ser a resposta, acho que muitas vezes é mais sensato:

  1. Criar uma interface e uma implementação padrão do seu Singleton
  2. Construir uma única instância de sua implementação padrão no “topo” do seu sistema. Isso pode ser em uma configuração Spring, ou em código, ou definido em uma variedade de formas, dependendo do seu sistema.
  3. Passe o único exemplo em cada componente que precisa dele (injecção dependência)

Outras dicas

Para compreender a maneira correta de resolver Singletons, você precisa entender o que está errado com Singletons (e estado global em geral):

singletons ocultar dependências.

Por que isso é importante?

Como Se você ocultar as dependências que tendem a pista perder da quantidade de acoplamento.

Você pode argumentar que

void purchaseLaptop(String creditCardNumber, int price){
  CreditCardProcessor.getInstance().debit(creditCardNumber, amount);
  Cart.getInstance().addLaptop();
}

é mais simples do que

void purchaseLaptop(CreditCardProcessor creditCardProcessor, Cart cart, 
                    String creditCardNumber, int price){
  creditCardProcessor.debit(creditCardNumber, amount);
  cart.addLaptop();
}

mas pelo menos o segundo API torna claro exatamente o que os colaboradores do método são.

Assim, a maneira de contornar Singletons não é usar variáveis ??estáticas ou prestadores de localizadores, mas para mudar as Singleton-classes em instâncias, que são instanciado no âmbito onde eles fazem sentido e injetadas nos componentes e métodos que precisam deles . Você pode usar uma IOC-estrutura para lidar com isso, ou você pode fazê-lo manualmente, mas o importante é livrar-se do seu estado global e fazer as dependências e colaborações explícito.

A melhor solução que eu deparei está usando o padrão de fábrica para construir instâncias de suas classes. Usando o padrão, você pode assegurar que existe apenas uma instância de uma classe que é compartilhado entre os objetos que o utilizam.

I que seria complicado de gerir, mas depois de ler este post "Para onde foram todos os Singletons ido?" , parece tão natural. E como um aparte, isso ajuda muito com isolar os testes de unidade.

Em resumo, o que você precisa fazer? Sempre que um objeto depende de outro, ele receberá uma instância de que só através de seu construtor (sem nova palavra-chave em sua classe).

class NeedyClass {

    private ExSingletonClass exSingleton;

    public NeedyClass(ExSingletonClass exSingleton){
        this.exSingleton = exSingleton;
    }

    // Here goes some code that uses the exSingleton object
}

E, em seguida, a fábrica.

class FactoryOfNeedy {

    private ExSingletonClass exSingleton;

    public FactoryOfNeedy() {
        this.exSingleton = new ExSingletonClass();
    }

    public NeedyClass buildNeedy() {
        return new NeedyClass(this.exSingleton);
    }
}

Como você irá instanciar sua fábrica apenas uma vez, haverá um único instanciação de exSingleton. Toda vez que você chamar buildNeedy, a nova instância do NeedyClass vai ser empacotado com exSingleton.

Espero que isso ajude. Por favor apontar eventuais erros.

Spring ou qualquer outro IoC-Container faz um trabalho razoavelmente bom nisso. Como as classes são criadas e gerenciadas fora do próprio aplicativo, o recipiente pode fazer classes simples singletons e injetá-las quando necessário.

Você não deveria ter que sair de seu caminho para evitar qualquer padrão. O uso de um padrão ou é uma decisão de projeto ou um ajuste natural (ele só cai no lugar). Quando você está criando um sistema, você tem a opção de usar um padrão ou não usar o padrão. No entanto, você não deve sair de seu caminho para evitar qualquer coisa que é finalmente uma escolha de design.

Eu não evitar o padrão Singleton. Ou é apropriado e eu usá-lo ou não é apropriado e eu não usá-lo. Eu acredito que é tão simples como isso.

A adequação (ou falta dela) do Singleton depende da situação. É uma decisão de design que devem ser feitas e as consequências dessa decisão deve ser entendido (e documentados).

O Singleton existe padrão, porque há situações em que um único objeto é necessário para fornecer um conjunto de serviços .

Mesmo se este for o caso eu ainda considerar a abordagem de criar singletons usando um campo estático global / propriedade que representa a instância, impróprio. É inapropriado porque criar uma dependência no código entre o campo estático e o objeto não, os serviços objeto fornece.

Então, ao invés do padrão clássico, solteirão, eu recomendo usar o serviço 'como' padrão com recipientes atendidos , onde em vez de usar o seu singleton através de um campo estático, você obter uma referência a ele através aa método solicitando o tipo de serviço necessário.

*pseudocode* currentContainer.GetServiceByObjectType(singletonType)
//Under the covers the object might be a singleton, but this is hidden to the consumer.

em vez de único mundial

*pseudocode* singletonType.Instance

Desta forma, quando você quiser alterar o tipo de um objeto de singleton para outra coisa, você vai ter e tempo fácil fazê-lo. Também como um benefício adicional e você não tem que passar em torno de colocar de instâncias de objetos para cada método.

Também veja Inversão de Controle , a idéia é que expondo singletons diretamente ao consumidor, você cria uma dependência entre o consumidor e a instância do objeto, e não o objecto serviços fornecidos pelo objeto.

A minha opinião é a de Ocultar o uso do padrão singleton sempre que possível, porque nem sempre é possível evitá-lo, ou desejável.

Monostate (descrito no Agile Desenvolvimento de Software de Robert C. Martin) é uma alternativa para Singleton. Neste padrão de dados da classe são estáticos, mas os getters / setters são não-estático.

Por exemplo:

public class MonoStateExample
{
    private static int x;

    public int getX()
    {
        return x;
    }

    public void setX(int xVal)
    {
        x = xVal;
    }
}

public class MonoDriver
{
    public static void main(String args[])
    {
        MonoStateExample m1 = new MonoStateExample();
        m1.setX(10);

        MonoStateExample m2 = new MonoStateExample();
        if(m1.getX() == m2.getX())
        {
            //singleton behavior
        }
    }
}

Monostate tem comportamento semelhante ao singleton mas fá-lo de uma forma onde o programador não é necessariamente conscientes do fato de que um singleton está sendo usado.

Se você estiver usando um Singleton para representar um único objeto de dados, você poderia, em vez passar objeto a dados em torno de como um parâmetro de método.

(embora, eu diria esta é a maneira errada de usar um Singleton, em primeiro lugar)

Se o seu problema é que você quer para manter o estado, você quer uma classe MumbleManager. Antes de começar a trabalhar com um sistema, o cliente cria um MumbleManager, onde Mumble é o nome do sistema. Estado é retido por isso. Provavelmente, o seu MumbleManager conterá um conjunto de propriedades que detém seu estado.

Este tipo de estilo se sente muito C-like e não muito objeto como -. Você verá que os objetos que definem o seu sistema, todos eles terão uma referência à mesma MumbleManager

Use um objeto simples e um objeto de fábrica. A fábrica é responsável por policiar a instância e apenas os detalhes simples objeto com as informações de configuração (que contém, por exemplo) e comportamento.

Na verdade, se você projetar direito a partir do zero em evitar Singeltons, você não pode ter que trabalhar em torno de não usar Singletons usando variáveis ??estáticas. Ao usar variáveis ??estáticas, você também está criando um Singleton mais ou menos, a única diferença é que você está criando diferentes instâncias de objetos, no entanto internamente todos eles se comportam como se estivessem usando um Singleton.

Você pode talvez dar um exemplo detalhado onde você usar um Singleton ou onde um Singleton é utilizado atualmente e que você está tentando evitar usá-lo? Isso poderia ajudar as pessoas a encontrar uma solução mais extravagante como a situação poderia ser tratado sem um Singleton em tudo.

BTW, eu pessoalmente não tenho problemas com Singletons e eu não consigo entender os problemas outras pessoas têm sobre Singletons. Não vejo nada de ruim sobre eles. Isto é, se você não está abusando-los. Cada técnica útil pode ser abusado e se está sendo abusado, ele irá levar a resultados negativos. Outra técnica que é comumente mal utilizado é herança. Ainda ninguém diria herança é algo ruim só porque algumas pessoas horrivelmente abusar dela.

Pessoalmente para mim Ð muito mais sensato maneira de implementar algo que se comporta como singleton é usar classe totalmente estático (membros estáticos, métodos estáticos, propriedades estáticas). Na maioria das vezes eu implementá-lo dessa maneira (eu não posso pensar de quaisquer diferenças de comportamento a partir do ponto de vista do usuário)

Eu acho que o melhor lugar para policiar o singleton está no nível de design de classe. Nesta fase, você deve ser capaz de mapear as interações entre as classes e ver se algo absolutamente, definitivamente exige que apenas 1 instância dessa classe é sempre na existência, em qualquer momento da vida aplicações.

Se for esse o caso, então você tem um singleton. Se você está jogando singletons no como uma conveniência durante a codificação, então você deve realmente ser revisitando o seu design e também parar de codificação disse singletons :)

E sim, 'polícia' é a palavra que quer dizer aqui, em vez de 'evitar'. O singleton não é algo a ser evitado (da mesma forma que Goto e variáveis ??globais não são algo a ser evitado). Em vez disso, você deve monitorar seu uso, e garantir que ele é o melhor método para obter o que deseja feito de forma eficaz.

Eu uso Singleton principalmente como "métodos container", com nenhum estado em tudo. Se eu preciso compartilhar estes métodos com muitas classes e querem evitar o fardo de instanciação e inicialização criar um contexto / session e inicializar todas as classes de lá; tudo o que se refere à sessão também tem acesso ao "singleton" assim contido.

Não Tendo programado em um ambiente intensamente orientada a objetos (por exemplo, Java), eu não sou completamente sobre os meandros da discussão. Mas eu ter implementado um singleton em PHP 4. Eu fiz isso como uma maneira de criar um manipulador de banco de dados 'caixa-preta' que automaticamente inicializado e não tem que ser passado para cima e para baixo chamadas de função em um quadro incompleto e pouco quebrado.

Depois de ler alguns links de padrões Singleton, eu não estou completamente certo que eu iria implementá-lo exatamente da mesma forma novamente. O que foi realmente precisava era de vários objetos com armazenamento compartilhado (por exemplo, a alça de banco de dados real) e isso é muito bonito o que o meu apelo se transformou em.

Como a maioria dos padrões e algoritmos, usando um singleton 'apenas porque é legal' é a Coisa do erro Para Do. Eu precisava de um verdadeiramente chamada 'caixa-preta' que passou a olhar muito como um singleton. E IMO essa é a maneira de abordar a questão:. Esteja ciente do padrão, mas também olhar para ele é escopo mais amplo e em que nível da instância deve ser único

O que quer dizer, quais são as minhas técnicas para evitá-lo?

Para "evitar"-lo, o que implica que existem muitas situações que me deparei em que o padrão Singleton é um naturalmente bom ajuste, e, portanto, que eu tenho que tomar algumas medidas para neutralizar essas situações.

Mas não há. Eu não tenho para evitar o padrão Singleton. Ele simplesmente não se coloca.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top