Patrón gemelo

Patrón de diseño de software

En ingeniería de software , el patrón Twin es un patrón de diseño de software que permite a los desarrolladores modelar la herencia múltiple en lenguajes de programación que no la admiten. Este patrón evita muchos de los problemas que presenta la herencia múltiple. [1]

Definición

En lugar de tener una única clase derivada de dos superclases, se tienen dos subclases independientes, cada una derivada de una de las dos superclases. Estas dos subclases están estrechamente acopladas, por lo que ambas pueden considerarse como un objeto gemelo con dos extremos. [1]

Aplicabilidad

El patrón gemelo se puede utilizar:

  • Para modelar la herencia múltiple en un lenguaje en el que no se admite la herencia múltiple.
  • para evitar algunos problemas de herencia múltiple. [1]

Estructura

Habrá dos o más clases padre que se suelen heredar. Habrá subclases, cada una de las cuales se deriva de una de las superclases. Las subclases están vinculadas entre sí a través de campos, y cada subclase puede anular los métodos heredados de la superclase. Los nuevos métodos y campos suelen declararse en una subclase. [1]

El siguiente diagrama muestra la estructura típica de la herencia múltiple:

Herencia múltiple típica
Herencia múltiple típica

[1]

El siguiente diagrama muestra la estructura del patrón Twin después de reemplazar la estructura de herencia múltiple anterior:

Patrón gemelo
Patrón gemelo

[1]

Colaboraciones

Cada clase secundaria es responsable del protocolo heredado de su clase principal. Maneja los mensajes de este protocolo y reenvía otros mensajes a su clase asociada. [1]

Los clientes del patrón gemelo hacen referencia a uno de los objetos gemelos directamente y al otro a través de su campo gemelo. [1]

Los clientes que dependen de los protocolos de las clases padre se comunican con objetos de la respectiva clase hija. [1]

Código de muestra

El siguiente código es un esquema de implementación de un tablero de juego de computadora con bolas en movimiento.

Clase para el tablero de juego:

 clase pública Gameboard extiende Canvas { int público ancho , alto ; GameItem público firstItem ; }             

[1]

Boceto de código para la clase GameItem:

clase pública abstracta GameItem { Tablero de juego tablero ; int posX , posY ; GameItem siguiente ; vacío público abstracto dibujar (); vacío público abstracto hacer clic ( MouseEvent e ); booleano público abstracto intersecta ( GameItem otro ); vacío público abstracto colisionar con ( GameItem otro );                                  comprobación pública nula () { GameItem x ;      para ( x = tablero . primerElemento ; x != null ; x = x . siguiente ) si ( interseca ( x )) colisionaCon ( x ); }              public static BallItem newBall ( int posX , int posY , int radio ) { // método de GameBoard BallItem ballItem = new BallItem ( posX , posY , radio ); BallThread ballThread = new BallThread ( ) ; ballItem.twin = ballThread ; ballThread.twin = ballItem ;                             devolver ballItem ; } }  

[1]

Boceto de código para la clase BallItem:

clase pública BallItem extiende GameItem { BallThread twin ; int radio ; int dx , dy ; booleano suspendido ;               public void draw ( ) { board.getGraphics ( ) . drawOval ( posX - radio , posY - radio , 2 * radio , 2 * radio ); }                 público void mover () { posX += dx ; posY += dy ; }           public void click () { if ( suspendido ) twin . resume (); else twin . suspend ();         suspendido = ! suspendido ; }     público booleano intersecta ( GameItem otro ) { si ( otra instancia de Muro ) devuelve posX - radio <= otro . posX && otro . posX <= posX + radio || posY - radio <= otro . posY && otro . posY <= posY + radio ; de lo contrario devuelve falso ; }                                      public void collideWith ( GameItem other ) { Muro muro = ( Muro ) otro ;           si ( pared . esVertical ) dx = - dx ; de lo contrario dy = - dy ; } }           

[1]

Boceto de código para la clase BallThread:

clase pública BallThread extiende Thread { BallItem gemelo ;        public void run () { while ( true ) { twin.draw ( ); / * borrar*/ twin.mover ( ); twin.draw ( ) ; } } }            

[1]

Implementación del patrón Twin

Se deben considerar las siguientes cuestiones:

  • Abstracción de datos: las clases asociadas de la clase gemela deben estar estrechamente acopladas, ya que probablemente tengan que acceder a los campos y métodos privados de cada una. En Java, esto se puede lograr colocando las clases asociadas en un paquete común y brindando visibilidad del paquete para los campos y métodos requeridos. En Modula-3 y en Oberon, las clases asociadas se pueden colocar en un módulo común.
  • Eficiencia: dado que el patrón Twin utiliza composición, que requiere reenvío de mensajes, puede ser menos eficiente que la herencia. Sin embargo, dado que la herencia múltiple es ligeramente menos eficiente que la herencia simple, la sobrecarga no será un problema importante. [1] [2]
  • Referencia cíclica: el patrón Twin se basa en que cada gemelo haga referencia al otro gemelo, lo que provoca un escenario de referencia cíclica. Algunos lenguajes pueden requerir que dichas referencias cíclicas se gestionen de manera especial para evitar una pérdida de memoria . Por ejemplo, puede ser necesario hacer que una referencia sea "débil" para permitir que se rompa el ciclo.

Véase también

Referencias

  1. ^ abcdefghijklmn Mössenböck, H., Twin: un patrón de diseño para modelar la herencia múltiple , Universidad de Linz, Instituto de software de sistemas
  2. ^ Stroustrup, B. (mayo de 1989), Herencia múltiple para C++ , Helsinki: Actas de la Conferencia de primavera de la EUUG
Retrieved from "https://en.wikipedia.org/w/index.php?title=Twin_pattern&oldid=1149632447"