1 Padrão: Singleton • Tipo - “Creational” • Objetivo - garantir que uma classe tenha apenas uma instância 2 Motivação • é importante para algumas classes ter apenas uma instância a cada momento – printer spooler – conversor A/D em filtro digital • como garantir que uma classe tem apenas uma instância e que esta instância é facilmente acessível? – variável global assegura acessibilidade mas não unicidade • melhor maneira é assegurar que a classe assegura a unicidade interceptando as mensagens de criação 3 Aplicabilidade • uma classe deve ter apenas uma instância e esta deve ter seu acesso indicado em um local claro • quanto esta instância única pode ser extensível por subclasseamento, sendo que clientes devem poder usar uma destas “instâncias estendidas” sem modificar seu código 4 Estrutura (figura) 5 Colaborações • Clientes obtém uma instância de Singleton apenas através da operação instância 6 Conseqüências • Acesso controlado à instância única • Redução do espaço de nomes – evita aumento incontrolável de variáveis globais • Permite refinamento de operações e representação – é fácil criar subclasse e é fácil configurar aplicação para utilizar instância desta nova subclasse – escolha da classe pode ser feita em tempo de execução 7 Conseqüências (cont.) • Permite um número variável de instâncias – com este padrão é fácil mudar a especificação e permitir mais de uma instância – pode-se usar a mesma abordagem para qualquer número finito determinado de instâncias • Mais flexível que operações em classes – outra maneira de implementar a mesma funcionalidade é utilizar operações de classes (métodos de classe em Smalltalk, funções Static em C++) – com ambas as técnicas acima é difícil mudar o “design” para possibilitar mais de uma instância por classe – funções estáticas em C++ nunca são virtuais, assim não podem ser re-definidas Implementação: assegurando unicidade – esconder a operação que cria a instância dentro de uma operação de classe que garante a unicidade – esta operação tem acesso à variável que armazena a instância única – em Smalltalk criamos nova versão de new new self error: ‘cannot create new object’ default SoleInstance isNil ifTrue:[SoleInstance:= super new]. ^ SoleInstance. 8 9 Assegurando unicidade: C++ – em C++ podemos definir a função estática instance: • class Singleton { • public: • static Sigleton* Instance(); • protected: //função é protegida • Singleton(); • private: • static Singleton* _instance; //como é ponteiro podemos usar sub-classe • }; • Singleton* Singleton::_instance = 0; • Singleton* Signelton::Instance(){ • if (_instance == 0) {_instance = new Singleton;} 10 Implementação: subclasses de Singleton • o problema não é criar a subclasse mas garantir a unicidade da instância mesmo na presença de subclasses • variável que guarda a instância única deve passar a ser inicializada com instância da subclasse • podemos determinar que instância usar no método Instance, onde guardamos indicação da subclasse a ser utilizada em uma “environment variable” • podemos escolher qual subclasse utilizar deferindo a implementação de Instance() para as subclasses, e “linkando” a classe desejada na fase final de montagem do programa 11 Criando subclasses de Singleton • utilizar um registro para as possíveis subclasses a serem utilizadas: – cada subclasse se registra com um nome pré-definido nos seus construtores – a função Instance() é alterada para: Singleton* Singleton::Instance(){ if (_instance == 0) { const char* singletonName = getenv(“SINGLETON”);//usupario fornece este variável _instance = Lokup(singletonname); } return _instance;} 12 Usos conhecidos • conjunto de mudanças do código na implementação de Smalltalk-80 da Parcplace • metaclasses tem apenas 1 instância • InterViews utiliza esta padrão para acessar a instância única das classes Session(define parâmetros de funcionamento da aplicação) e WidgetKit (define o “look and feel” das interfaces) 13 Padrões Relacionados • vários padrões podem ser implementados utilizando Singleton, em particular – Abstract Factory – Builder – Prototype