Címlap Programozás A gyártófüggvény (Factory Method)
A gyártófüggvény (Factory Method) PDF Nyomtatás E-mail
Olvasóink értékelése: / 3
ElégtelenKitűnő 
Hírek - Programozás, tervezés
Írta: Carlos   
A gyártófüggvény egy létrehozási minta, amely mentesíti a kliens oldalt a létrehozandó objektumok típusának ismeretétől, és az azzal járó többletlogika implementálásától.

Factory MethodA gyártófüggvény bevetése a következő feltételek esetén megfontolandó:
- kliens (azaz hívó) oldalon egy öröklődési hierarchiában szerepelő osztályok példányosítását végezzük el (a new hívások nagy sűrűsége árulkodó jel lehet)  
- kiaknázzuk a többalakúságban rejlő lehetőségeket (az adott osztályok rendelkeznek virtuális függvényekkel)

A többalakúság (polimorfizmus) elegáns megoldásoat tesz lehetővé.
Az ősosztály pointerén keresztül hivatkozunk egy tagfüggvényre, és futásidőben a rendszer beazonosítja a megfelelő példányt, és a megfelelő osztály virtuális függvénye kerül meghívásra.
A típust a kód írásakor csak egy kivételes esetben kell megadnunk - éspedig a példányosításkor (létrehozáskor a megfelelő típus konstruktorát kell meghívnunk).

Az alábbi kódrészlet ezt a megvalósítást mutatja be:

// ősosztály
class BaseMesh
{
public:
   virtual void render() = 0;
};

class SolidMesh : public BaseMesh
{
public:
    void render()
    {
        cout << "SolidMesh: rendering...\n";
    }
};

class WireframeMesh : public BaseMesh
{
public:
    void render()
    {
        cout << "WireframeMesh: rendering...\n";
    }
};

class TexturedMesh : public BaseMesh {
public:
    void render()
    {
        cout << "TexturedMesh: rendering...\n";
    }
};

int main( void )
{
    // lista a megjelenítendő objektum-poinetrek nyilvántartására
    vector renderQueue;
    int meshType;

    // feltöltjük a megjelenítendő objektumok listáját
    while (true)
    {
        cout << "SolidMesh(1) WireframeMesh(2) TexturedMesh(3) Go(0): ";

        cin >> meshType;
        
        if (meshType == 0)
        {
            break;
        }
        else if (meshType == 1)
        {
            renderQueue.push_back( new SolidMesh );
        }
        else if (meshType == 2)
        {
            renderQueue.push_back( new WireframeMesh );
        }
        // default ág
        else
        {
            renderQueue.push_back( new TexturedMesh );
        }
    }
    // meghívjuk az objektumok render függvényét
    for ( int i = 0; i < renderQueue.size(); ++i )
    {
        renderQueue[i]->render();
    }
    // nagytakarítás
    for ( int i = 0; i < renderQueue.size(); ++i )
    {
        delete renderQueue[i];
    }
}


Ez a megvalósítás kikényszeríti, hogy a kliens ismerje a példányosítandó típusokat. Magyarán a main függvényben minden egyes típust ismernünk kell ahhoz, hogy a new operátor segítségével példányosítsuk őket.)
Emiatt minden új típus megjelenésekor bővítenünk kell a hívó oldal kódját; ha például bevezetünk egy MultitexturedMesh típust, akkor egy új "else if" ágban kell lekezelnünk a létrehozását.

A kliens tehermentesíthető a típusok ismeretétől, a megoldást pedig a gyártófüggvény jelenti.
A gyártófüggvénynek természetesen ismernie kell az új típust, mivel a létrehozása itt történik meg.
A következő kódsorok a gyártófüggvény egy lehetséges megvalósítását mutatja be; a makeMesh() gyártófüggvényt egy statikus tagfüggvényként definiáljuk a BaseMesh ősosztályban:

class BaseMesh {
public:
   // Factory Method
   static BaseMesh* makeMesh( int choice );
   virtual void render() = 0;
};

// a gyártófüggvény implementációja
BaseMesh* BaseMesh::makeMesh( int meshType )
{
    BaseMesh* meshPtr = null;
    if ( meshType == 1 )
    {
        meshPtr = new SolidMesh();
    }
    else if ( meshType == 2 )
    {
        meshPtr = new WireframeMesh();
    }
    else
    {
        meshPtr = TexturedMesh();
    }
    return meshPtr;
}


int main( void ) {
   vector renderQueue;
   int meshType;
   
   // feltöltjük a megjelenítendő objektumok listáját
   // a lényeges különbség az előző verzióhoz képest az,
   // hogy nem jelennek meg a származtatott BaseMesh típusok (SolidMesh, WireframeMesh, illetve TexturedMesh)
   // és a new operátor sem szerepel - helyette a BaseMesh::makeMesh( meshType ) fv.-t hívjuk meg
   while (true)
   {
        cout << "SolidMesh(1) WireframeMesh(2) TexturedMesh(3) Go(0): ";
        
        cin >> meshType;
        
        if (meshType == 0)
        {
            break;
        }
        
        renderQueue.push_back( BaseMesh::makeMesh( meshType ) );
    }
    // meghívjuk az objektumok render függvényét
    for ( int i = 0; i < renderQueue.size(); ++i )
    {
        renderQueue[i]->render();
    }
    // nagytakarítás
    for ( int i = 0; i < renderQueue.size(); ++i )
    {
        delete renderQueue[i];
    }
}

class SolidMesh : public BaseMesh {
public:
    void render()
    {
        cout << "SolidMesh:  rendering...\n";
    }
};

class WireframeMesh : public BaseMesh
{
public:
    void render()
    {
        cout << "WireframeMesh:  rendering...\n";
    }
};

class TexturedMesh : public BaseMesh
{
public:
    void render()
    {
        cout << "TexturedMesh:  rendering...\n";
    }
};


Sikerélményekben gazdag kódírást!

Nyisztor Károly
http://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.