Unul din “design patterns” foarte hulit, totodata foarte folosit, si mai ales prost inteles, in mintea multora fiind echivalent cu variabila globala.
Este un termen care insa se refera la Object Oriented Programming, si in general nu are a face cu variabilele globale. Un Singleton e pur si simplu o clasa care odata instantiata nu va permite crearea reinstantierea. Orice incercare de reinstantiere trebuie sa intoarca o referinta la instanta deja existenta.
Pentru a asigura acest comportament trebuie sa observam ca nu avem cum sa ranforsam “unicitatea” decat avand un constructor privat. In aplicatiile care ofera procesare concurenta trebuie de asemenea sa ne asiguram cumva de aceasta unicitate, clasica fiind folosirea mutex pe metoda care intoarce instanta.
Voi da un exeemplu generic din PHP5. constructorul e privat, clone e definit pt a limita clonarea, getInstance e functia publica pe care o vom folosi. $_instance si getInstance() sunt statice, ceea ce inseamna ca pot fi apelate chiar daca clasa nu e instantiata. Ca sidenote, proprietatile si metodele statice nu pot fi apelate prin operatorul sageata “->”, iar cuvantul cheie $this nu are inteles intr-o metoda statica. Iata de ce orice metoda sau proprietate statica poate fi apelata doar prin “sintaxa” className :: myName () respectiv ClassName::$myName
class singleton (
private $myData = array();
private static $_instance = null;
private function __construct() {}
protected function __clone() {}
static public function getInstance() {
if(is_null(self::$_instance))
{
self::$_instance = new self();
}
return self::$_instance;
}
public function import() {...}
public function get() {...}
}
Ce este insa dificil folosind Singleton Pattern ? Pai testarea ar fi una dintre ele. Daca pentru a testa un modul ai nevoie de un mockup object in locul singletonului, si atunci avem o problema. Presupunand ca avem o clasa :
MyClassThatUsesTheSingleton {
...
public function __construct($settings=null) {
$this->;myData = Singleton::getInstance();
}
...
}
putem redefini constructorul cam asa
MyClassThatUsesTheSingleton {
...
public function __construct($myMockup=null) {
if (is_null($myMockup)) {
$this->;myData = Settings::getInstance();
}
else {
$this->t;myData=$settings;
}
}
...
}
si astfel am rezolvat problema.
Desigur ca se pune intrebarea “la ce e bun singleton”. Eh, nu la prea multe. Un obiect in care sa tii setarile e una din primele chestii care vin in minte. De asemenea in unele aplicatii dorim ca daca avem deja o conexiune la o baza de date s-o folosim pe accea. Exista insa deja conexiuni persistente, probabil mult mai sane de folosit (mai ales in aplicatii web) . Sau daca avem nevoie de log-uri. Logging-ul in general inseamna un obiect apelabil global .
Pentru a afla daca chiar avem nevoie de un singleton trebuie sa vedem daca fiecare parte a aplicatiei pe care o dezvoltam va avea nevoie de o singura instanta a clasei noaste. De asemenea trebuie sa fim siguri ca toate clasele vor apela acest obiect in acelasi fel. Desi este un pattern destul de des folosit, nu este foarte intelept sa-l suprafolosim doar de dragul faptului ca suna cool.