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.
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).
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).
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.
A következő diagram a többszörös öröklődés tipikus struktúráját mutatja: centre|Typical multiple inheritance
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ó: centre|Twin pattern
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é. 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. 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.
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;
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; }}
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();
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.
Jegyzetek
Fordítás
Kategória:Programtervezési minták Kategória:Java-kódpéldák