En enxeñaría de software, o padrón de deseño **Singleton** (Instancia Única) emprégase para garantir que unha clase soamente teña unha instancia, ademais de proporcionar un punto de acceso global a esa instancia. Trátase polo tanto dun padrón de creación.

É de utilidade cando se necesita exactamente un obxecto para coordinar accións nun sistema. Este concepto pode xeneralizarse para restrinxir a instanciación a un certo número de obxectos.

Motivación
----------

En certos contextos, é importante que algunhas clases teñan exactamente unha instancia que sexa facilmente accesible (por exemplo, ter un único xestor de ventás nunha aplicación).

O uso dunha variable global fai accesible un obxecto, pero non evita que se poidan crear múltiples instancias de obxectos. Unha solución mellor é facer que sexa a propia clase a responsable da súa única instancia. A clase pode garantir que non se poida crear ningunha outra instancia (restrinxindo o acceso ao construtor) e pode así mesmo proporcionar un modo de acceso á instancia.

Aplicabilidade
--------------

O uso do padrón é axeitado cando:

* Deba existir unha única instancia dunha clase, que debe ser accesible aos clientes dende un punto de acceso ben coñecido.
* A única instancia pode ser estendida (subclase), e os clientes deberían poder utilizar a instancia estendida sen modificar o seu código.

Estrutura
---------

Participantes
-------------

* **Instancia Única** (Singleton): define un *método de clase* que permite aos clientes accederen á instancia única. Normalmente é responsable de crear a súa única instancia.

Colaboracións
-------------

Os clientes acceden á instancia do Singleton a través da operación definida con esa finalidade.

Consecuencias
-------------

As principais **vantaxes** do padrón Singleton son:

* Proporciona un *acceso controlado á súa única instancia* grazas á encapsulación da mesma, podendo ter un control estrito sobre o acceso a ela por parte dos clientes.
* *Reduce o espazo de nomes* ao evitar o uso de variables globais para almacenar instancias.
* Posibilita o *refinamento de operacións e representación;* é dicir, pódense crear subclases da clase Singleton, sendo sinxelo configurar os sistemas cunha instancia desta clase estendida.
* *Permite un número variable de instancias*, sendo necesario cambiar unicamente a operación que proporciona acceso á instancia do Singleton.
* Outorga unha *maior flexibilidade* con respecto ás operacións de clase, pois o uso destas dificulta o cambio dos deseños para permitir máis dunha instancia.

Implementación
--------------

Á hora de utilizar o padrón Singleton, débense ter en conta algúns aspectos de implementación, entre os que destacan:

* *Garantir a unicidade da instancia da clase.*
* *Estender a clase Singleton.*

### Garantir a unicidade da instancia da clase

O padrón Singleton fai que a única instancia sexa unha instancia normal da clase, pero coa particularidade de que dita clase soamente permite crear unha instancia. Adóitase conseguir isto mediante a ocultación da operación que crea a instancia tras unha operación de clase. Esta operación ten acceso á variable que contén a instancia e asegura que a variable estea inicializada con dita instancia previamente a devolver o seu valor. Este enfoque asegura que un Singleton se crea e inicializa antes do seu primeiro uso. Por exemplo, en Java pódese definir a operación de clase mediante un método estático `obterInstancia()` da clase `Singleton`, que tamén define unha variable estática `_instancia` que contén a súa única instancia.

```
public class Singleton {
 private static Singleton \_instancia = null;
 
 private Singleton() { }
 
 public static synchronized Singleton obterInstancia() {
 if (\_instancia == null) {
 \_instancia = new Singleton();
 }
 return \_instancia;
 }
}

```

Os clientes acceden ao Singleton exclusivamente a través do método `obterInstancia()`. A variable `_instancia` inicialízase a `null` e o método estático `obterInstancia()` devolve o seu valor, inicializándoa coa única instancia en caso de que sexa `null`. `obterInstancia()` utiliza inicialización "preguiceira" (*lazy initialization*): o valor que devolve non se crea e almacena ata que se accede a el por primeira vez.

Por outra banda, o construtor declárase como privado: un cliente que trate de crear unha instancia de `Singleton` directamente obterá un erro en tempo de compilación. Isto garante que soamente se pode crear unha instancia. Ademais, e debido a que `_instancia` é de tipo `Singleton`, o método `obterInstancia()` pode asignar a esta variable unha instancia dunha subclase de `Singleton`.

Nótese o uso de `synchronized` para permitir a súa utilización en *aplicacións multi-fío*. No caso de que dous fíos executen o método de creación simultaneamente cando a instancia do Singleton aínda non existe, ambos deben comprobar a instancia do Singleton e soamente debe creala un deles. Por iso é típico o uso de *exclusión mutua* na clase que indica que o obxecto está sendo instanciado.

Unha alternativa sería o uso de inicialización "impaciente" (*eager initialization*), na que sempre se crea a instancia. Este tipo de inicialización emprégase cando o programa sempre necesita unha instancia ou cando o custo de crear a instancia non é demasiado alto en términos de tempo/recursos.

```
public class Singleton {
 private static Singleton \_instancia = new Singleton();

 private Singleton() { }

 public static Singleton obterInstancia() {
 return \_instancia;
 }
}

```

Este método ten varias vantaxes:

* Non se necesita utilizar `synchronized` no método `obterInstancia()`.
* O programador non ten que preocuparse da creación de instancias, pois Java garante que a inicialización xa estará feita antes de que o código sexa accedido por **calquera** clase.

Porén, tamén ten algúns inconvenientes. Destaca principalmente:

* Se o programa non necesita a instancia do Singleton, pode ser unha mellor opción o uso da inicialización "preguiceira".

### Estender a clase Singleton

O principal problema non é definir a subclase, senón crear a súa única instancia de maneira que os clientes a poidan utilizar. En esencia, a variable que fai referencia á única instancia debe ser inicializada cunha instancia da subclase. A técnica máis sinxela é determinar que Singleton queremos usar na operación `obterInstancia()` de `Singleton`.

Outra maneira de elixir a subclase de `Singleton` é trasladar a implementación de `obterInstancia()` dende a clase pai á subclase. Este enfoque dificulta a elección da clase de Singleton en tempo de execución, mentres que utilizar instrucións condicionais para determinar a subclase é máis flexible, pero fixa o conxunto de posibles clases Singleton. Ningún dos dous enfoques é o suficientemente flexible para tódolos casos.

Un enfoque máis flexible utiliza un *rexistro de obxectos Singleton*. Así, en lugar de que sexa `obterInstancia()` quen defina o conxunto de posibles clases Singleton, estas clases poden rexistrar a súa única instancia polo seu nome nun rexistro que sexa coñecido por todos.

O rexistro establece unha correspondencia entre nomes e obxectos Singleton. Cando `obterInstancia()` necesita un Singleton, consulta o seu rexistro, pedindo un Singleton polo seu nome. O rexistro busca o Singleton correspondente (no caso de que exista) e devólveo. Así, `obterInstancia()` non ten que coñecer tódalas posibles clases de Singleton. Todo o que necesita é unha interface común para tódalas clases de Singleton que inclúa operacións para o rexistro.

Exemplos de implementación
--------------------------

### Java

A continuación amósase un exemplo no que se utiliza o padrón Singleton. Trátase dunha táboa onde claves e valores son cadeas de caracteres. O padrón Singleton garante que tódolos clientes utilizarán soamente a instancia única, é dicir, a mesma táboa hash (utilizada internamente para representar a táboa asociativa).

```
class Main {

 static void buscar() {

 // Obsérvese que en lugar de crear un obxecto de tipo Dicionario (o cal é
 // imposible debido a que o construtor é privado) o que se fai é chamar
 // ao método de clase instancia() para obter a instancia única.
 Dicionario d = Dicionario.instancia();

 System.out.println("O valor asociado a can é "+ d.buscar("can"));
 System.out.println("O valor asociado a oso é "+ d.buscar("oso"));
 }

 static void engadir() {
 Dicionario d = Dicionario.instancia();

 d.engadir("gato", "cat");
 d.engadir("can", "dog");
 d.engadir("rato", "mouse");
 d.engadir("oso", "bear");
 d.engadir("león", "lyon");
 }

 static public void main(String argv[]) {
 engadir();
 buscar();
 }
}

class Dicionario {

 // A clase Singleton garda un atributo de clase, normalmente privado, que
 // mantén a referencia coa única instancia da clase.
 static private Dicionario \_instancia;

 // Estado privado asociado coa instancia única.
 private Hashtable \_taboa;

 // O construtor da clase, que crea a táboa de dispersión, é privado
 // para garantir que non se poidan crear instancias dende fóra da clase.
 private Dicionario() {
 \_taboa = new Hashtable();
 }

 // O método de clase instancia() encárgase de crear a instancia
 // asociada ao Singleton a primeira vez que se solicita. En accesos
 // posteriores, devólvese a instancia orixinal.
 static Dicionario instancia() {
 if (\_instancia == null) {
 \_instancia = new Dicionario();
 }

 return \_instancia;
 }

 // Estes dous métodos son aplicables sobre obxectos da clase Dicionario,
 // é dicir, a súa única instancia. Engaden e buscan elementos na táboa hash.
 // Dado que a táboa hash almacena obxectos de tipo Object (igual que o
 // vector) debemos facer unha conversión ao extraer elementos da táboa.

 public void engadir(String clave, String valor) { 
 \_taboa.put(clave, valor); 
 }

 public String buscar(String clave) { 
 return (String) \_taboa.get(clave); 
 }
}

```

Padróns relacionados
--------------------

* Algúns dos padróns que se poden implementar facendo uso do Singleton son o Abstract Factory (Fábrica Abstracta), o Builder (Construtor virtual) e o Prototype (Prototipo).
* Tamén é habitual que os obxectos Facade (Fachada) sexan Singletons debido a que soamente se require un obxecto Facade.

Véxase tamén
------------

|  |  |
| --- | --- |
|  | Commons ten máis contidos multimedia sobre:  ***Singleton*** |

### Bibliografía

* *Design Patterns. Elements of Reusable Object-Oriented Software* - Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides - Addison Wesley (GoF- Gang of Four)

### Outros artigos

* padrón de deseño
* Abstract Factory

|  |  |
| --- | --- |
| Control de autoridades | 
* Wd: Q746699
* MAG: 135089680

 |