Singleton pattern v PHP 5.3

V mojom prvom riadnom príspevku do nového blogu prejdem rovno k veci, ktorej sa práve venujem. Začnem technickým článkom pre programátorov v PHP. Opíšem návrh, ktorý som použil v mojej práve programovanej práci. PHP od verzie 5.3 obsahuje zaujímavú funkciu, get_called_class(). Táto nenápadná funkcia nám tak otvára nové možnosti návrhu tried. Vracia totiž triedu neskorej statickej väzby.

Odbočka: Čo je to neskorá statická väzba?

Neskorá statická väzba umožňuje získať názov volanej triedy zo statickej funkcie triedy, z ktorej sa dedí. Príklad prevzatý zo stránok manuálu PHP: <?php class foo { static public function test() { echo get\_called\_class(); } } class bar extends foo {} foo::test(); // Vypise foo bar::test(); // Vypise bar ?>

Singleton pattern

Singleton pattern je návrhový vzor, keď z danej triedy chceme mať len 1 instanciu, ktorú chceme, aby sa vytvorila pri prvom volaní a neskôr sa uchovávala v pamäti. A teraz si ukážeme, ako si pomocou tejto technológie vyrobiť Singleton pattern, ktorý by sme inak museli písať do každej triedy zvlášť.

 <?php abstract class Singleton { private static $instances = array(); protected function \_\_construct() {} protected function \_\_clone() {} final public static function getInstance() { $calledClass = get\_called\_class(); if(!isset(self::$instances&#91;$calledClass&#93;)) self::$instances&#91;$calledClass&#93; = new $calledClass(); return self::$instances&#91;$calledClass&#93;; } } ?> 
Premenná $instances uchováva instancie objektov podľa mena. V ďalších riadkoch zakážeme **verejnú **konštrukciu **alebo **klonovanie objektu. Metóda getInstance() už potom robí to, čo má robiť pri klasickom Singleton.

Príklad použitia
 <?php class DB extends Singleton { //... telo triedy ... protected __construct() { //... skonstruujeme objekt ako by sme to bezne robili ... } } // V dalsom kode volame jednoducho $db = DB::getInstance(); ?> 
Pre článok som povolil komentáre. Píšte svoje názory.

  • pmajster

    http://www.patrikstrba.eu/2009/12/php-navrhovy-vzor-singleton/
    spoločná téma wordpressu, spoločná téma článku, v oboch prípadoch bez akéhokolvek vysvetlenia praktického využitia…
    len mne ušliel cieľ/pointa článku?

  • admin

    Téma Mystique je v dobe písania komentára 3. najpopulárnejšia (http://wordpress.org/extend/themes/browse/popular/), okrem iného sa páči mne aj tebe.

    Ak si všimneš, je rozdiel medzi mojim a tvojim článkom v tom, že moje riešenie používa Singleton ako abstraktnú triedu (teda dá sa veľmi jednoducho znova použiť pre iné triedy). V PHP <5.3 sa to týmto štýlom nedalo napísať.

    Pointa? Pointou je poukázať na fakt, že PHP 5.3 nie je len ďalšou verziou, ale obsahuje veľké zmeny a otvára nové možnosti návrhu tried.

    Kde som vzal inšpiráciu? (akosi implicitne položená otázka) Písal som Setup panel pre hostingovú spoločnosť, kde sa využívalo veľa Singleton tried, (DB, Auth, Domain, HostingPlan, ...). Tak som si povedal, že s tým niečo spravím a napísal som abstraktnú triedu. Samozrejme, googlil som veľa, ako aj každý programátor, no som si istý, že tvoju stránku som nikdy predtým nevidel.

  • Gandalph

    Jaky je duvod oznaceni te tridy jako abstract, kdyz v ni nemas jedinou abstract metodu?

  • Tomáš Srna

    No sama o sebe moc uzitocna neni, nechajme len aby sa z nej len dedilo :)

  • Gandalph

    No je to zajimavy zpusob, jak zabranit Singleton::getInstance(), ale neslo by to vyresit nejak elegantneji, nez aby to v takovem pripade hodilo Fatal error uvnitr kodu te metody getInstance?

  • Tomáš Srna

    Abstraktne triedy sa bezne pouzivaju. Tento sposob korektne reaguje na nekorektnu snahu ziskat instanciu niecoho neuzitocneho.

  • Gandalph

    Ano, ale pokud mas v kodu vickrat volani toho getInstance tak potom nenajdes v cem je chyba… myslim, ze by lepsi bylo pridat do kodu getInstance:
    $ref = new ReflectionClass($calledClass);
    if($ref->isAbstract()) throw new Exception(“Pokus o vytvoreni instance abstraktni tridy”);

    S pouzitim Exception si pak muzes pomoci try…catch a metody getTrace/getTraceAsString zjistit, v cem je problem

  • Tomáš Srna

    Da sa to samozrejme obalit vychytavkami typu ReflectionClass. Cielom clanku bolo ale poukazat na zaujimave riesenie Singletonu.

    To, ako si to programator vo svojej implementacii “vymaluje” roznymi vychytavkami, neriesi uz tento clanok.