Tvillingmönster
Inom mjukvaruteknik är Twin -mönstret ett mjukvarudesignmönster som gör det möjligt för utvecklare att modellera flera arv i programmeringsspråk som inte stöder multipelt arv. Detta mönster undviker många av problemen med multipelt arv.
Definition
Istället för att ha en enda klass som är härledd från två superklasser, ha två separata underklasser som var och en härrör från en av de två superklasserna. Dessa två underklasser är nära kopplade, så båda kan ses som ett tvillingobjekt med två ändar.
Tillämplighet
Tvillingmönstret kan användas:
- att modellera multipelt arv på ett språk där multipelarv inte stöds
- för att undvika vissa problem med multipla arv.
Strukturera
Det kommer att finnas två eller flera föräldraklasser som används för att ärvas. Det kommer att finnas underklasser som var och en kommer från en av superklasserna. Underklasserna är ömsesidigt länkade via fält, och varje underklass kan åsidosätta metoderna som ärvts från superklassen. Nya metoder och fält deklareras vanligtvis i en underklass.
Följande diagram visar den typiska strukturen för multipelt arv:
Följande diagram visar tvillingmönsterstrukturen efter att ha ersatt den tidigare multipelarvsstrukturen:
Samarbeten
Varje barnklass är ansvarig för det protokoll som ärvt från sin förälder. Den hanterar meddelanden från detta protokoll och vidarebefordrar andra meddelanden till sin partnerklass.
Klienter av tvillingmönstret refererar direkt till ett av tvillingobjekten och det andra via dess tvillingfält.
Klienter som förlitar sig på överordnade klassers protokoll kommunicerar med objekt i respektive barnklass.
Exempelkod
Följande kod är en skissad implementering av ett datorspelbräde med rörliga bollar.
Klass för spelplanen:
public class Gameboard utökar Canvas { public int width , height ; public GameItem firstItem ; … }
Kodskiss för GameItem-klassen:
public abstract class GameItem { Gameboard board ; int posX , posY ; GameItem nästa ; offentlig abstrakt void draw (); public abstract void click ( MouseEvent e ); offentliga abstrakta booleska skär ( GameItem annat ); public abstract void collideWith ( GameItem other ); public void check () { GameItem x ; for ( x = board . firstItem ; x != null ; x = x . next ) if ( skär ( x )) kolliderar med ( x ); } public static BallItem newBall ( int posX , int posY , int radius ) { //method of GameBoard BallItem ballItem = new BallItem ( posX , posY , radius ); BallThread ballThread = ny BallThread (); ballArtikel . tvilling = bollTråd ; bollTråd . twin = ballArtikel ; returnera bollArtikel ; } }
Kodskiss för BallItem-klassen:
public class BallItem utökar GameItem { BallThread twin ; int radie ; int dx , dy ; boolesk suspenderad ; public void draw () { board . getGraphics (). drawOval ( posX - radie , posY - radie , 2 * radie , 2 * radie ); } public void move () { posX += dx ; posY += dy ; } public void klicka på () { if ( suspended ) twin . CV (); annars tvilling . suspendera (); avstängd = ! avstängd ; } public boolean intersects ( GameItem other ) { if ( other instansof Wall ) return posX - radius <= other . posX && annat . posX <= posX + radie || posY - radie <= annan . posY && annat . posY <= posY + radie ; annars returnerar falskt ; } public void collideWith ( GameItem other ) { Wall wall = ( Wall ) other ; if ( vägg . ärVertikal ) dx = -dx ; _ annat dy = - dy ; } }
Kodskiss för BallThread-klassen:
public class BallThread utökar tråden { BallItem twin ; public void run () { while ( true ) { twin . rita (); /*radera*/ tvilling . flytta (); tvilling . rita (); } } }
Implementering av tvillingmönstret
Följande frågor bör övervägas:
- Dataabstraktion - partnerklasser i tvillingklassen måste vara tätt kopplade, eftersom de förmodligen måste komma åt varandras privata fält och metoder. I Java kan detta uppnås genom att placera partnerklasserna i ett gemensamt paket och ge paketsynlighet för de nödvändiga fälten och metoderna. I Modula-3 och i Oberon kan partnerklasser placeras i en gemensam modul.
- Effektivitet - Eftersom tvillingmönstret använder komposition som kräver vidarebefordran av meddelanden, kan tvillingmönstret vara mindre effektivt än arv. Men eftersom multipelarv ändå är något mindre effektivt än enkelarv, kommer omkostnaderna inte att vara ett stort problem.
- Cyklisk referens - Tvillingmönstret förlitar sig på att varje tvilling refererar till den andra tvillingen, vilket orsakar ett cykliskt referensscenario. Vissa språk kan kräva att sådana cykliska referenser hanteras speciellt för att undvika en minnesläcka . Till exempel kan en referens behöva göras "svag" för att cykeln ska kunna bryta.
Se även
- Adaptermönster , speciellt tvåvägsadapter