Címlap Programozás Az Egyke (Singleton) tervezési minta
Az Egyke (Singleton) tervezési minta PDF Nyomtatás E-mail
Olvasóink értékelése: / 0
ElégtelenKitűnő 
Hírek - Programozás, tervezés
Írta: Carlos   

Ígéretemhez híven folytatom tervezési mintákat bemutató cikksorozatomat.

Az egyik legalapvetőbb és valószínűleg leggyakrabban használt minta az egyke minta. A neve is mutatja legfőbb jellemvonását: az adott osztályból egyetlen példány jön létre az alkalmazás futása során.
Erre akkor van szükség, ha az adott objektumból felesleges, sőt zavaró lenne több példányt létrehozni; jó példa erre a hibanaplózó vagy teszem azt az XML-feldolgozó osztály.
 
A cél tehát egy olyan módszer bevezetése, amely garantálja, hogy mindössze egy objektumot lehet létrehozni az osztályból.
Az első, szembeötlő nehézség az, hogy az osztály konstruktorát bárki meg tudja hívni - ezt kell megakadályozzuk.
A megoldás a konstruktor elrejtése - tegyük priváttá, és ezzel megakadályozzuk a közvetlen példányosítást. Azonban valahogy biztosítanunk kell az osztály példányosítását, hiszen különben mindössze egy használhatatlan osztályt kaptunk.
Ezt a célt szolgálja az Instance() tagfüggvény, amely az egyetlen osztálypéldány létrehozásáért felelős.
Az osztály egyetlen példánya az első Instance() hívás során jön létre, az ezt követő hívások pedig ezt a példányt adják vissza.


Singleton design patternEgy Singleton osztály (avagy Egyke) létrehozásának menete:
- rejtsük el a ctor-okat, a másoló ctor-t és az "operator =" -t (ezáltal lehetetlenné tesszük a közvetlen példányosítást)
- deklaráljuk az adattaghoz történő hozzáférését biztosító, static public metódust (általában Instance() névre hallagat)
- deklaráljuk az osztály példánymutatóját statikus privát adattagként (ez az adott osztályra egyetlen példányának címe)
- gondoskodjunk arról, hogy az első hozzáféréskor létrehozzuk az egyetlen osztálypéldányt, minden azt követő híváskor pedig a már létező objektumpoinetrt adjuk vissza


Kérdés
Miért statikus az Instance() metódus? Hamarosan jön a kézenfekvő magyarázat, de előbb vizsgáljuk meg a kódot:

public class Singleton
{
    // példány
    private static Singleton instance;
 
    public static Singleton Instance()
    {
        // csak akkor hozzuk létre,
        // ha korábban ez nem történt meg
        if (instance == null)
        {
          instance = new Singleton();
        }
        return instance;
    };
    public void fv()
    {
        //...
    };

    // ctor-ok és az értékadó operátor elrejtése, a közvetlen példányosítás megakadályozására
    private Singleton() {};
    private Singleton( const Singleton& );
    private Singleton& operator =( const Singleton& );       
}


A következő kódrészlet a példányosítás módját mutatja be:
// a kliensoldali kód
int main()
{
    // egyke létrehozása / lekérdezése
    Singleton obj = Singleton.Instance();
    obj.fv()
    //...
}


Az előző kérdésre - azaz, hogy miért static az Instance() tagfüggvény? - a fenti kódrészletben található a válasz: az osztálynak eredetileg nincs érvényes példánya, és érvényes példánymutató nélkül pedig nem tudunk meghívni nem-statikus tagfüggvényeket.
A statikus függvények kivételt képeznek, hiszen az osztálypéldány megléte nem előfeltétel. (A statikus függvények korlátja, hogy kizárólag statikus adattagokon dolgozhatnak.)

Az egyik felmerülő gond a fenti Singleton megvalósítással a konkurens hozzáférés. Ha több szálból (nagyjából) egyszerre hívják az Instance() függvényt, előfordulhat,
hogy az if( instance == null ) ellenőrzést egyszerre hajtják végre, majd több példány is létrejön, hiszen a feltétel egyik szálnál sem teljesült.
Erre természetesen vannak megfelelő megoldások és nyelvi elemek, de a többszálúság rejtelmeibe egyelőre nem szeretnék jobban belemenni (mindazonáltal egy következő cikksorozat témája lehet, addig meg hagyatkozzatok google barátunkra ;-)).

További jó kódolást mindenkinek!
Nyisztor Károly
www.nyisztorkaroly.org

 
SEO by Artio

Legfrisebb fórumbejegyzések

Részletek...

Támogatja a Joomla!. Designed by: Joomla Theme, linux hosting. Valid XHTML and CSS.