Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Uniwersalna klasa Singleton
Forum PHP.pl > Forum > PHP > Object-oriented programming
tompaw
Witam forumowiczow.

W swoim projekcie chcialem wykorzystac klasy Singleton. Nie chce jednak w kazdej z nich tworzyc osobno tego samego mechanizmu (czyli funkcji get_instance). Postanowilam napisac klase Singleton, a pozostale tworzyc w oparciu o nia. Niestety, pojawil sie problem.

Klasa Singleton wyglada tak:

  1. <?php
  2. class Singleton {
  3.  
  4. private static $instance = null;
  5.  
  6. private function __construct() {
  7. }
  8.  
  9. public static function GI() {
  10. if (self::$instance == null) {
  11. self::$instance = new Singleton;
  12. }
  13.  
  14. return self::$instance;
  15. }
  16. };
  17. ?>


Pozniej pojawia sie jakas prosta klasa pochodna i wywolanie jej metody:

  1. <?php
  2. class Controller extends Singleton {
  3.  
  4. // stuff here...
  5.  
  6. function test() {
  7. }
  8.  
  9. };
  10.  
  11. Controller::GI()->test();
  12. ?>


Oczywiscie ten kod zwroci blad:

Fatal error: Call to undefined method Singleton::test() in test.php on line x

i jest to zrozumiale. Problem tkwi w jednej linijce metody Singleton::GI(), a mianowicie:

  1. <?
  2. self::$instance = new Singleton;
  3. ?>


Przez to metoda ta jest na sztywno przypisana do klasy Singleton, ktora w moim przypadku jest klasa czysto wirtualna, tzn chce, aby sluzyla jako podstawa dla innych klas.

Moje pytanie brzmi: jak sprawic, aby tworzony byl obiekt nie klasy Singleton, ale klasy pochodnej od niej, na rzecz ktorej wywolywana jest metoda GI() ?

Probowalem dostac sie do nazwy tej klasy dwojako: przez get_class() oraz __CLASS__. Niestety, zawsze zwracana jest klasa Singleton.

Z gory dzieki za pomoc, pozdrawiam.
bela
  1. <?php
  2. class Singleton {
  3.  
  4. private static $instance = array;
  5.  
  6. private function __construct() {
  7. }
  8.  
  9. public static function GI( $name ) {
  10. if (self::$instance[$name] == null) {
  11. self::$instance[$name] = new $name;
  12. }
  13.  
  14. return self::$instance[$name];
  15. }
  16. };
  17. ?>


moze cos takiegO ?

  1. <?php
  2. class Controller extends Singleton {
  3.  
  4. // stuff here...
  5.  
  6. function test() {
  7. }
  8.  
  9. };
  10.  
  11. Controller::GI()->test();
  12. ?>


zle sie odwołujesz powinienes
  1. <?php
  2. $object = object::GI();
  3. $object->test();
  4.  
  5. ?>
tompaw
Tylko ze z Twoja propozycja to trzeba by wywolywac funkcje:

ClassName::GI("ClassName")

tak ?

Dlaczego wywolanie Controller::GI()->test(); jest wg Ciebie zle ?
hawk
Odwołanie Controller::GI()->test() jest jak najbardziej poprawne.

To co bela666 proponuje to już nie będzie singleton.

@tomapaw: tego się raczej nie da zrobić. Nie tylko w php, w innych językach również. Chociaż w php miałoby to większe szanse powodzenia, bo php jest interpretowany.
bela
Cytat(hawk @ 2004-11-08 10:33:38)
To co bela_666 proponuje to już nie będzie singleton.

a czemu ?
hawk
Bo to będzie Rejestr. Była jeszcze jakaś inna, mądrzejsza nazwa, ale nie zmienia to faktu, że rejestr to nie singleton. Inny wzorzec.

Bo Singleton służy do teo, aby była tylko jedna instancja klasy, a w twoim przykładzie w ogóle nie będzie żadnej instancji klasy Singleton.

Bo w zależności od tego co podamy, dostajemy obiekty różnej klasy, a singleton powinien zawsze dawać tą samą instancję.

Po prostu - inny wzorzec. Ani lepszy, ani gorszy, ale na pewno nie singleton. Co nie zmienia faktu że rejestry często są przy okazji singletonami.
tompaw
hm... rozwiazalem to w ten sposob:

  1. <?
  2.  
  3. class Singleton {
  4.  
  5. private static $instance = null;
  6.  
  7. private function __construct() {
  8. }
  9.  
  10. public static function &GetInstance($name) {
  11. if (self::$instance[$name] == null) {
  12. self::$instance[$name] = & new $name; 
  13. }
  14.  
  15. return self::$instance[$name];
  16. }
  17. };
  18.  
  19. class SingletonManager {
  20.  
  21. function &GI($type) {
  22. eval(&#092;"$new_object = \".$type.\"::GetInstance(\"\".$type.\"\");\");
  23. return $new_object;
  24. }
  25.  
  26. }
  27.  
  28. ?>


opinie, komentarze, itp ;>
Vengeance
a na ciorta tak ?

jak masz tą pierwszą klase to mozesz juz

Singleton::GetInstance('jakasklasa');
czyba nie ?
bela
Cytat(tompaw @ 2004-11-08 19:53:20)
hm... rozwiazalem to w ten sposob:

  1. <?
  2.  
  3. class Singleton {
  4.  
  5. private static $instance = null;
  6.  
  7. private function __construct() {
  8. }
  9.  
  10. public static function &GetInstance($name) {
  11. if (self::$instance[$name] == null) {
  12. self::$instance[$name] = & new $name; 
  13. }
  14.  
  15. return self::$instance[$name];
  16. }
  17. };
  18.  
  19. class SingletonManager {
  20.  
  21. function &GI($type) {
  22. eval(&#092;"$new_object = \".$type.\"::GetInstance(\"\".$type.\"\");\");
  23. return $new_object;
  24. }
  25.  
  26. }
  27.  
  28. ?>


opinie, komentarze, itp ;>

przecież hawk powiedział, że to nie singleton dry.gif
tompaw
Cytat(Vengeance @ 2004-11-08 19:41:46)
a na ciorta tak ?

jak masz tą pierwszą klase to mozesz juz

Singleton::GetInstance('jakasklasa');
czyba nie ?

jak tak teraz na to patrze to chyba rzeczywiscie =]
hawk
Tylko dlaczego w kółko pojawiają się wątki o singletonie, które kończą się tym, że singleton jest olewany i staje na czymś zupełnie innym?

Singleton - najbardziej nadużywany wzorzec wszechczasów.
Ozzy
http://zend.com/zend/week/week209.php => TLK: New overloading feature?
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.