Iker programtervezési minta
A szoftverfejlesztésben, az iker minta egy programtervezési minta, ami lehetővé teszi a fejlesztőknek, hogy megvalósíthassák a többszörös öröklődést, olyan programozási nyelvekben, amik ezt nem támogatják. A mintával elkerülhetjük a többszörös öröklődéssel kapcsolatos problémák nagy részét.[1]
Definíció
Ahelyett, hogy létrehoznánk egy osztályt ami két szülő-osztályból származik, hozzunk létre inkább két külön gyerek-osztályt, egyiket az egyik, másikat a másik szülő-osztályból örökítve. A gyerek-osztályok szorosan csatoltak, így együttesen egy „iker objektumként“ tekinthetünk rájuk, aminek két külön felülete van (egy az egyik szülőtől származó funkcionalitáshoz, egy pedig a másik szülőtől származóhoz).[1]
Alkalmazhatóság
Az Iker programtervezési mintát használhatjuk:
- többszörös öröklődés megvalósításához, olyan nyelvekben ahol ez nem támogatott;
- néhány többszörös öröklődésből adódó probléma elkerülésére (mint például a szülő-osztályok tagjai közötti név ütközések).[1]
Struktúra
Lesz két vagy több szülő-osztály, amit örökíteni akarunk. Mindegyikhez lesz egy gyerek-osztály, ami a szülő-osztályok egyikéből származik. A gyerek-osztályok kölcsönösen össze vannak kapcsolva mezők segítségével (csatoltság), és bármely gyerek-osztály felülírhatja a szülő-osztályból örökölt metódusait. Új metódusokat és mezőket általában csak a gyerekosztályok egyikében deklarálunk.[1]
A következő diagram a többszörös öröklődés tipikus struktúráját mutatja:
[1]
Az alábbi diagramon pedig az (előzőleg bemutatott többszörös öröklődést kiváltó) iker minta struktúrája látható:
[1]
Együttműködések
- Minden gyerek-osztály felelős a szülő-osztályától örökölt protokollért. A gyerek kezeli az ehhez a protokollhoz tartozó üzeneteket, az egyéb üzeneteket pedig továbbítja a társ osztálya felé.[1]
- Az iker minta kliensei csak az iker objektumok egyikére hivatkoznak közvetlenül, a többire (testvérek) pedig ennek az objektumnak a mezőin keresztül.[1]
- A kliensek, amik a szülő osztályok protokolljaira támaszkodnak, az adott szülőnek megfelelő (abból származtatott) gyerek-osztály objektumaival kommunikálnak.[1]
Példa kód
A következő kód, egy mozgó golyókkal működő számítógépes táblajáték implementációjának vázlata.
a játéktáblához tartozó osztály:
public class Gameboard extends Canvas { public int width, height; public GameItem firstItem; … }
kódvázlat a GameItem (játékelem) osztályhoz:
public abstract class GameItem { Gameboard board; int posX, posY; GameItem next; public abstract void draw(); public abstract void click (MouseEvent e); public abstract boolean intersects (GameItem other); public abstract void collideWith (GameItem other); public void check() { GameItem x; for (x = board.firstItem; x != null; x = x.next) if (intersects(x)) collideWith(x); } public static BallItem newBall (int posX, int posY, int radius) {//method of GameBoard BallItem ballItem = new BallItem(posX, posY, radius); BallThread ballThread = new BallThread(); ballItem.twin = ballThread; ballThread.twin = ballItem; return ballItem; } }
[1]
kódvázlat a BallItem (golyó) osztályhoz:
public class BallItem extends GameItem { BallThread twin; int radius; int dx, dy; boolean suspended; public void draw() { board.getGraphics().drawOval(posX-radius, posY-radius, 2*radius, 2*radius); } public void move() { posX += dx; posY += dy; } public void click() { if (suspended) twin.resume(); else twin.suspend(); suspended = ! suspended; } public boolean intersects (GameItem other) { if (other instanceof Wall) return posX - radius <= other.posX && other.posX <= posX + radius || posY - radius <= other.posY && other.posY <= posY + radius; else return false; } public void collideWith (GameItem other) { Wall wall = (Wall) other; if (wall.isVertical) dx = - dx; else dy = - dy; }}
[1]
kódvázlat a BallThread („golyómozgató“ programszál) osztályhoz:
public class BallThread extends Thread { BallItem twin; public void run() { while (true) { twin.draw(); /*erase*/ twin.move(); twin.draw(); } } }
[1]
Iker minta megvalósítása
A következő szempontokat érdemes figyelembe venni:
- Adat absztrakció - az „iker osztály“ együttműködő osztályai (testvérek) erősen csatoltak kell hogy legyenek, mivel valószínűleg el kell tudniuk érni egymás privát mezőit és metódusait. Java-ban ezt úgy érhetjük el, hogy a testvér osztályokat egy közös csomagba (package) rakjuk, és csomag szintű láthatóságot adunk a szükséges mezőknek és metódusoknak. Modula-3-ban és Oberon-ban az együttműködő osztályok egy közös modulba kerülhetnek.
- Hatékonyság - Az iker minta kompozíciót használ, ami üzenet-továbbítást igényel, emiatt az iker minta kevésbé hatékony lehet, mint az öröklődés. Mivel azonban a többszörös öröklődés némileg kevésbé hatékony mint az egyszeres öröklődés, az üzenet továbbításból fakadó többlet munka nem okoz komoly problémát.[1][2]
Jegyzetek
- ↑ a b c d e f g h i j k l m Mössenböck, H., Twin - A Design Pattern for Modelling Multiple Inheritance, University of Linz, Institute for System Software
- ↑ Stroustrup, B. (May 1989), Multiple Inheritance for C++, Helsinki: Proceeding EUUG Spring Conference
Fordítás
- Ez a szócikk részben vagy egészben a Twin Pattern című angol Wikipédia-szócikk ezen változatának fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.