Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Automatyczny singleton.
Forum PHP.pl > Forum > PHP > Object-oriented programming
Koleś
Cześć. Kiedyś programując w C++ nauczyłem się pisać ciekawy wzorzec, który nazywał się automatycznym singletonem. Swoją "automatyczność" zawdzięcza temu, że można po nim odziedziczyć podając jako parametr szablonu nazwę klasy pochodnej (dziedziczącej). IMHO takie rozwiązanie jest o wiele wygodniejsze. Pomyślałem, że można coś takiego napisać w PHP:

  1. <?php
  2. class Singleton
  3. {
  4. protected static $type = false;
  5.  
  6. protected function __construct() {}
  7. public function SetType( $type_ )
  8. {
  9. self::$type = $type_;
  10. }
  11.  public static function Instance()
  12.  {
  13. static $instance;
  14. if( ! self::$type )
  15. {
  16. throw new Exception( 'Po Singletonie należy odziedziczyć' );
  17. }
  18. if( ! isset( $instance ) ) $instance = new self::$type;
  19. return $instance;
  20.  }
  21. }
  22. ?>


  1. <?php
  2. class Test extends Singleton
  3. {
  4. public function Show() { echo 'abcd <br />'; }
  5. }
  6. ?>


  1. <?php
  2. Test::SetType( 'Test' );
  3. Test::Instance()->Show();
  4. ?>


Co o tym sądzicie?
Turgon
Po co dawać setType przecie zasadniczo, to działa bez naszej pomocy. Wystarczy dać self.
Według mnie to powinno być tak:
  1. <?php
  2. class Singleton
  3. {
  4. protected static $instance;
  5.  
  6. protected function __construct() {}
  7. public static function Instance(){
  8. if( !isset(self::$instance)) self::$instance = new self();
  9. return self::$instance;
  10.  }
  11. }
  12. ?>


Nie testowałem smile.gif
Ale potem robisz tylko:

  1. <?php
  2. class Tester extends Singleton{
  3.  public function showTest(){
  4. echo 'My name is '.get_class().' and I am using singleton! ';
  5.  }
  6. }
  7. ?>


  1. <?php
  2. Tester::Instance()->showTest();
  3. ?>
SongoQ
@Koleś Tutaj czegos takiego nie masz. Singleton to singleton, przyklad masz w manualu bo co na sile kombinowac.
Koleś
Cytat(Turgon @ 4.03.2007, 11:27:14 ) *
Wystarczy dać self.

Aha, dzięki, nie wiedział, że to jest możliwe tongue.gif
Cytat(SongoQ @ 4.03.2007, 11:45:32 ) *
@Koleś Tutaj czegos takiego nie masz. Singleton to singleton, przyklad masz w manualu bo co na sile kombinowac.

Po to, żeby nie trzeba było pisać tego samego kodu w kilku klasach.
Athlan
@Turgon, mala przyczepka tongue.gif Linia 8 Twojego kodu mogłaby wyglądać tak:

  1. <?php
  2. if(!(self::$instance instanceof self)) self::$instance = new self();
  3. ?>


Kiedyś byłem bliski przypadkowi, że zamieniam statyczną $instance i się dziwiłem dlaczego mam errora, a instancja jest w środku... po prostu to nie była instancja smile.gif
Turgon
Wolnoć Tomku w swoim domku !

Dla mnie nie ma większej różnicy powiem szczerze smile.gif
splatch
Co do singletonu jako wzorca mam kilka zastrzeżeń.

Dziedziczenie singletonów w PHP nie działa, ponieważ odwołanie do self w metodzie zawsze tyczy się klasy, w której ta metoda została zaimplementowana. Przykład:
  1. <?php
  2.  
  3. class HelloWorld {
  4.  
  5. protected static $_oInstance = null;
  6. protected $_sUniqueIdentyficator = null;
  7.  
  8. protected function __construct() {
  9. $this->_sUniqueIdentyficator = md5( sha1( time() * rand(1, 999) ) );
  10. }
  11.  
  12. public static function Instance() {
  13. if(!self::$_oInstance instanceof self)
  14. self::$_oInstance = new self;
  15. return self::$_oInstance;
  16. }
  17.  
  18. public function SayHello() {
  19. echo 'Hello World! ID: ' . $this->_sUniqueIdentyficator ."n";
  20. }
  21. }
  22. class HelloWorldChildren extends HelloWorld {
  23.  
  24. public function SayHello() {
  25. echo 'Childern says hello World! ID: ' . $this->_sUniqueIdentyficator ."n";
  26. }
  27. }
  28. $oHello1 = HelloWorld::Instance();
  29. $oHello1->SayHello();
  30.  
  31. $oHello2 = HelloWorld::Instance();
  32. $oHello2->SayHello();
  33.  
  34. $oHello3 = HelloWorldChildren::Instance();
  35. $oHello3->SayHello();
  36.  
  37. $oHello4 = HelloWorldChildren::Instance();
  38. $oHello4->SayHello();
  39.  
  40. echo get_class($oHello1) ."n";
  41. echo get_class($oHello3);
  42.  
  43. ?>


W ogóle ten temat to pomyłka, i to dość spora, ktoś pisze o implementacji singletonu w PHP...
hwao
Brak uniemożliwienia klonowania obiektu.

Czemu klasa nie jest abstrakcyjna? Nie był by potrzebny ten Exception().

Swoją drogą lepiej już napisać obiekt rejestru/fabryki w którym była by przechowywana i tworzona jedna instancja danej klasy.
Athlan
@splatch, o widzę przykład z mojego bloga tongue.gif

http://athlan.vgroup.pl/singleton-registry-map/

Cytat
Dziedziczenie singletonów w PHP nie działa, ponieważ odwołanie do self w metodzie zawsze tyczy się klasy, w której ta metoda została zaimplementowana.


Mój przykład wyświetla coś innego, sprzecznego z Twoją wypowiedzią:

Kod
Hello World! ID: 90593c18e926b6f8cc33b261b02201a7
Hello World! ID: 90593c18e926b6f8cc33b261b02201a7
Hello World! ID: 90593c18e926b6f8cc33b261b02201a7
Hello World! ID: 90593c18e926b6f8cc33b261b02201a7
HelloWorld
HelloWorld
Turgon
Athlan: Tak bez obrazy, ale twój przykład potwierdza kolega o nie dziedziczeniu. Ja tylko klasę przerobiłem na PHP i nie testowałem w ogóle...
Athlan
Cytat
Athlan: Tak bez obrazy, ale twój przykład potwierdza kolega o nie dziedziczeniu. Ja tylko klasę przerobiłem na PHP i nie testowałem w ogóle...

Jak to o NIE dziedziczeniu?

Skoro rodzic "wykonuje" instację samego siebie, a dziecko które próbuje wykonać instancję i posiada instancję taką, jaką postada rodzic to singleton jest dziedziczony (przekazywany dziecku). smile.gif
splatch
Cytat(Athlan @ 10.03.2007, 19:15:30 ) *
Jak to o NIE dziedziczeniu?

Skoro rodzic "wykonuje" instację samego siebie, a dziecko które próbuje wykonać instancję i posiada instancję taką, jaką postada rodzic to singleton jest dziedziczony (przekazywany dziecku). smile.gif

Nie. self jest zależny od kontekstu metody. Jeśli metoda Instance() jest zadeklarowana w klasie HelloWorld to odnosi się do HelloWorld. Jeżeli zatem odwołujesz się do HelloWorldChildren::Instance nie nadpisując tej metody to kontekst się nie zmienia i jest to wciąż HelloWorld. W Javie odwołania statyczne np są zawsze zależne od klasy z której wywołanie następuje, czyli w HelloWorld.Instance() zwróci instancję HelloWorld i logicznie HelloWorldChildren.Instance() zwróci instancję HelloWorldChildren.

Zwróć uwagę, że $this zachowuje się inaczej i nie jest zależne od metody a od klasy. To jest po prostu bug w PHP. W metodzie statycznej nie jesteś w stanie pobrać nazwy klasy, z której została ona wywołana.
UDAT
Cytat(keo @ 27.06.2007, 21:57:24 ) *
zgadzam sie w 100%

Po co przytakujesz wypowiedzi sprzed 4 miesięcy?


A co do automatycznego singletona -> można to zrobić w prosty sposób za pomocą programowania aspektowego. Przykład takiego użycia umieściłem na blogu, gdyż zajęłoby to zbyt dużo miejsca na forum.
NuLL
Cytat
Po co przytakujesz wypowiedzi sprzed 4 miesięcy?

Mowisz sam do siebie ? snitch.gif

Mowiac prawde UDAT ten twoj pomysl jest niewiele wart bo malo ktory admin poinstaluje ci rozszerzenia PECL ktore chcesz.
UDAT
To rozszerzenie wymagane jest tylko podczas łączenia aspektów z kodem klas. Do uruchomienia samych klas nie jest potrzebne - tak więc możesz używać powstałego kodu na dowolnym hostingu.


Cytat(NuLL @ 29.06.2007, 11:27:22 ) *
Mowisz sam do siebie ? snitch.gif

Kto usunął tego posta? blinksmiley.gif
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.