A 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
| < Előző | Következő > |
|---|





