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]
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]
Az Iker programtervezési mintát használhatjuk:
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:
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ó:
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();
}
}
}
A következő szempontokat érdemes figyelembe venni: