2011-09-10 3 views
6

Wszystkie widoczne wzorce singleton używają odniesienia do obiektu, aby określić, czy obiekt został utworzony. Jednak jeśli używam pojedynczego singletona, aby zagwarantować tylko jedno połączenie db, dlaczego nie użyć łącza do łącza db w tym celu? Oto kod, którego używam. (PS: działa dobrze). Używam komentarza, aby móc łatwo wyszukiwać moje zajęcia.Prostszy singleton

/*one*/ 

class one 
    { 
    public static $db; 
    private function __construct() 
    { 
    self::$db=new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DATABASE); 
    } 
    public static function get() 
    { 
    if(self::$db==NULL) 
     { 
     new self(); 
     } 
    return self::$db; 
    } 
    } 
+1

+1 za pomysłowość! – Clive

+1

Jest nadal singleton. Nic nietypowego, powiedziałbym. – Smar

+2

Errr ... Nikt nie widzi, że metoda get zwraca inny obiekt? – Macmade

Odpowiedz

5

W PHP, konstruktor nie zwraca.

Tak więc twoja metoda get zwraca obiekt one, po raz pierwszy jest wywoływany, a następnie obiekt mysqli. Prawdopodobnie nie tego chcesz.

if(self::$_db == NULL) 
{ 
    return new self(); // Here you return an object of class one 
} 
else 
{ 
    return self::$_db; // Here you return an object of type mysqli 
} 

Jeśli chcesz zwrócić przedmiot mysqli, nie trzeba pojedyncza, gdyż nie ma potrzeby tworzenia instancji obiektu, który znajduje się tylko tutaj, aby powrócić wystąpienie innego obiektu.

Schemat rejestru byłby lepszy w takim przypadku.

Jeśli potrzebujesz metod (otoki dla twojego obiektu DB), stwórz prawdziwy singleton.

EDIT

Sprawdziłem zaktualizowaną kod. Teraz zwracasz zawsze instancję mysqli. Ale nie musisz tworzyć własnego obiektu. To całkowicie bezużyteczne ...

Jeśli naprawdę chcesz przejść do swojego wzorca, jak powiedział złoty, w statycznej instancji, sprawdza, czy self::db jest NULL. Jeśli tak, tworzy instancję mysqli i przypisuje ją do self::db. Następnie zwraca go.

public static getDatabaseInstance() 
{ 
    if(self::$_db == NULL) 
    { 
     self::$_db = new mysqli(...); 
    } 

    return self::$_db; 
} 

Ustaw również konstruktor jako prywatny, aby użytkownicy nie mogli tworzyć niepotrzebnych wystąpień Twojej klasy. Albo lepiej ich upublicznienie i wyjątek:

public function __construct() 
{ 
    throw new Exception('This class is not supposed to be instantiated'); 
} 
+0

Z dokumentacji PHP: 'void __construct ([mixed $ args [, $ ...]])'. Zobacz "void"? http://php.net/manual/en/language.oop5.decon.php – Macmade

+1

Oznacza to, że wartość zwracana jest ignorowana. Więc nawet jeśli zwrócisz coś (inny obiekt), nie zmodyfikuje on typu obiektu utworzonego przez 'new'. – Macmade

+0

Zobacz moją edycję ...:) – Macmade

0
class one 
{ 
    private static $_selfInstance; 
    public $db; 
    private function __construct() 
    { 
    } 
    public function getDb() 
    { 
     if($this->db == null) 
     $this->db=new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DATABASE); 
     return $this->db; 

    } 

    public static function getInstance() 
    { 
     if(!(self::$_selfInstance instanceof self)) { 
     self::$_selfInstance= new self(); 
     } 
     return self::$_selfInstance; 
    } 
} 

Dostęp

$db = one::getInstance()->getDb(); 
+1

Czy był jakiś powód, aby opuścić drugie 'n' w' $ _selfInstace'? – jcolebrand

1

Zakładając mam poprawnie parsowania pytanie, pytasz, czy to w porządku, aby użyć nieważności $db aby upewnić się, że tylko jedną instancję; to jest całkowicie poprawny sposób robienia rzeczy, i tak naprawdę to polecam. PHP null jest wyraźnie przeznaczone do reprezentowania zmiennej o "bez wartości" - idealne dopasowanie do niezainicjowanego stanu wzorca singleton.

Zazwyczaj te rzeczy będą wywoływane tylko za pomocą intuicyjnej nazwy, np. SomeAppDbConn.

0

Jak już wspomniano, metoda constructor nie zwraca niczego poza instancją klasy. Zakładając, że zawsze chcesz tego samego wystąpienia mysqli, oto jak to zrobić.

class DBInstance 
{ 
    protected static $db; 

    private function __construct() 
    { 
     // intentionally empty 
    } 

    public static function get() 
    { 
     if(self::$db === NULL) 
     { 
      self::$db=new mysqli(DB_HOST, DB_USER, DB_PASS, DB_DATABASE); 
     } 

     return self::$db; 
    } 
} 

Z całą pewnością jest to wzór singletonowy z dodatkową premią oddzielania instancji od instancji klasy.

+0

Rejestr byłby lepszy, IMHO. Lub przynajmniej deklaruje konstruktor prywatny, aby uniknąć niepotrzebnych wystąpień klasy. – Macmade

+0

Prawo jesteś i zgadzam się z tobą na korzystanie z rejestru. Z drugiej strony, korzystanie z tej metody jest z pewnością szybsze, jeśli tworzysz naprawdę małą aplikację, w której połączenie z bazą danych jest jedynym dopasowaniem do tego schematu. Co myślisz? – gilden

+0

Pewnie, i wygląda na to, że chce tego w ten sposób ...:) – Macmade

3

Definiowanie działa dobrze :)

Spróbuj:

  • porównać mieszań obiekt zwrócony z obu metod (nie ma znaczenia, jeśli użyć obiektu klonowanie)
  • połączyć się z DB przy użyciu różne dane uwierzytelniające (np. w testach jednostkowych)
  • odłączyć od DB i ponownie podłączyć
  • zresetować wystąpienie obiekt (teraz tworząc 1000 obiektów przy użyciu new wypełnia pamięć w górę)
  • powiedzieć innemu programistce do stworzenia w tej klasie, na pewno poszukać metody one::getInstance(). Jak odgaduje zachowanie tej klasy?

Singletony dotyczą stanu globalnego. Wygląda na to, że masz globalny stan i trochę bałaganu.