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ó
szerkesztésAhelyett, 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
szerkesztésAz 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
szerkesztésLesz 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:
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ó:
Együttműködések
szerkesztés- 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
szerkesztésA 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
szerkesztésA 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
szerkesztésFordítás
szerkeszté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.