Método de plantilla (patrón de diseño)
método de plantilla |
---|
método de plantilla |
Tipo de |
conductual |
Estructura |
|
Descrito en Patrones de diseño |
Sí |
Un método de plantilla es un patrón de diseño de comportamiento que define la base de un algoritmo y permite a los sucesores redefinir algunos pasos del algoritmo sin cambiar su estructura como un todo.
Aplicabilidad
- Uso único de la parte invariable del algoritmo, dejando la parte cambiante a criterio de los herederos.
- Localización y aislamiento de código común a varias clases para evitar duplicaciones.
- Permita que los herederos amplíen el código solo en ciertos lugares.
Miembros
Clase abstracta (clase abstracta): define las operaciones abstractas que se reemplazan en los herederos para implementar los pasos del algoritmo; implementa un método de plantilla que define el esqueleto del algoritmo. El método de plantilla llama a las operaciones reemplazadas y otras definidas en la clase Abstract.
Clase concreta (clase concreta): implementa las operaciones reemplazadas de la manera necesaria para esta implementación.
La clase Concrete asume que los pasos invariantes del algoritmo se realizarán en AbstractClass .
Ejemplos
En los ejemplos, el método de plantilla se implementa para juegos.
Texto fuente en C++11
/**
* Una clase abstracta que es común a varios juegos en
los que * los jugadores juegan contra otros, pero solo uno está
* jugando en un momento dado.
*/
clase GameObject
{
protegido :
int CuentaJugadores ;
virtual bool EndOfGame () = 0 ;
vacío virtual InitializeGame () = 0 ;
virtual void MakePlay ( jugador int ) = 0 ;
vacío virtual PrintWinner () = 0 ;
público :
/* Un método de plantilla: */
void PlayOneGame ( int playersCount )
{
PlayersCount = playersCount ;
InicializarJuego ();
int j = 0 ;
while ( ! Fin del juego ()) {
Hacer Jugar ( j );
j = ( j + 1 ) % jugadoresCount ;
}
ganador de impresión ();
}
};
clase Monopoly : GameObject público
{
protegido :
/* Implementación de métodos concretos necesarios */
void InitializeGame () anular
{
// Inicializar dinero
}
invalidar la anulación de MakePlay ( jugador int )
{
// Procesar un turno de jugador
}
anular bool EndOfGame ()
{
devolver verdadero ;
}
anular PrintWinner () anular
{
// Mostrar quién ganó
}
};
Ajedrez de clase : GameObject público
{
protegido :
/* Implementación de métodos concretos necesarios */
void InitializeGame () anular
{
// Poner las piezas en el tablero
}
invalidar la anulación de MakePlay ( jugador int )
{
// Procesar un turno para el jugador
}
anular bool EndOfGame ()
{
// Devuelve true si se ha llegado a Jaque mate o Stalemate
return true ;
}
anular PrintWinner () anular
{
// Mostrar el jugador ganador
}
};
int principal ()
{
GameObject * juego = nuevo Monopoly ();
juego -> PlayOneGame ( 2 );
devolver 0 ;
}
Fuente Java
paquete com.designpatterns.templatemethod ;
/* Códigos de variación del juego.
*
* Archivo GameCode.java
* */
public enum GameCode {
AJEDREZ ,
MONOPOLIO
}
/* Una clase abstracta cuya implementación de métodos abstractos será específica para cada tipo de juego.
*
* Archivo Juego.java
* */
Juego de clase pública abstracta {
cantidad de jugadores privados int ;
Vacío abstracto protegido initializeGame ();
juego vacío abstracto protegido ();
endGame vacío abstracto protegido ();
printWinner abstracto vacío protegido ();
playOneGame public final void ( int cantidad de jugadores ){ set Cantidad de jugadores ( cantidad de jugadores );
inicializarJuego ();
jugarJuego ();
final del juego ();
imprimirGanador ();
}
public void setPlayersAmount ( int playersAmount ){
esto . cantidad de jugadores = cantidad de jugadores ;
}
}
paquete com.designpatterns.templatemethod ;
/* Juego "Ajedrez". Específicamente para ajedrez, implementa los métodos de la clase Game.
*
* Archivo Ajedrez.java
* */
El ajedrez de clase pública extiende el juego {
@Override
protected void initializeGame () {
// acciones de inicialización específicas del ajedrez
}
@Override
protected void playGame () {
// acciones de juego específicas de ajedrez
}
@Override
protected void endGame () {
// Acciones específicas de ajedrez para finalizar un juego
}
@Override
protected void printWinner () {
// acciones específicas de ajedrez para imprimir el ganador
}
}
paquete com.designpatterns.templatemethod ;
/* Juego de monopolio. Específico de Monopoly, implementa los métodos de la clase Game.
*
* Archivo Monopoly.java
* */
El monopolio de clase pública extiende el juego {
@Override
protected void initializeGame () {
// acciones de inicialización específicas del monopolio
}
@Override
protected void playGame () {
// acciones de juego específicas del monopolio
}
@Override
protected void endGame () {
// acciones específicas de monopolio para finalizar un juego
}
@Override
protected void printWinner () {
// acciones específicas del monopolio para imprimir el ganador
}
}
paquete com.designpatterns.templatemethod ;
/* Una clase que muestra cómo funciona el patrón de diseño del método de plantilla.
*
* Archivo GamesManager.java
* */
administrador de juegos de clase pública {
public static void main ( String [] args ){ código de juego
final código de juego = código de juego . AJEDREZ ;
juego juego _
cambiar ( código de juego ) {
caso AJEDREZ :
juego = nuevo Ajedrez ();
romper ;
caso MONOPOLY :
juego = nuevo Monopoly ();
romper ;
predeterminado :
lanza una nueva IllegalStateException ();
}
juego _ jugar un juego ( 2 );
}
}
Texto fuente en C#
/**
* Una clase abstracta que es común a varios juegos en
los que * los jugadores juegan contra otros, pero solo uno está
* jugando en un momento dado.
*/
namespace Design_Patterns
{
class TemplateMethodPattern
{
clase abstracta interna GameObject { protected int PlayersCount ;
resumen protegido bool EndOfGame ();
resumen vacío protegido InitializeGame ();
resumen vacío protegido MakePlay ( jugador int );
abstracto vacío protegido PrintWinner ();
/* Un método de plantilla: */
public void PlayOneGame ( int playersCount )
{
PlayersCount = playersCount ;
InicializarJuego ();
var j = 0 ;
while (! EndOfGame ())
{
MakePlay ( j );
j = ( j + 1 ) % jugadoresCount ;
}
ganador de impresión ();
}
}
//Ahora podemos extender esta clase para implementar juegos reales:
public class Monopoly : GameObject
{
/* Implementación de métodos concretos necesarios */
protected override void InitializeGame ()
{
// Inicializa el dinero
}
protected override void MakePlay ( int player )
{
// Procesar un turno de jugador
}
protected override bool EndOfGame ()
{
return true ;
}
protected override void PrintWinner ()
{
// Mostrar quién ganó
}
/* Declaraciones específicas para el juego Monopoly. */
// ...
}
Ajedrez de clase pública : GameObject {
/* Implementación de métodos concretos necesarios */
protected override void InitializeGame ()
{
// Poner las piezas en el tablero
}
protected override void MakePlay ( int player )
{
// Procesar un turno para el jugador
}
protected override bool EndOfGame ()
{
return true ;
// Devuelve verdadero si se ha llegado a Jaque mate o Stalemate
}
protected override void PrintWinner ()
{
// Mostrar el jugador ganador
}
/* Declaraciones específicas para el juego de ajedrez. */
// ...
}
Prueba de vacío estático público () { GameObject juego = nuevo Monopoly ();
juego _ Juego PlayOne ( 2 );
}
}
}
Código fuente en Python
de abc import ABCMeta , método abstracto
Unidad de clase ( metaclase = ABCMeta ):
"""
Una unidad abstracta. Los atributos de clase que comienzan con un guión bajo en python
están protegidos
"""
def __init__ ( self , velocidad : int ) -> Ninguno :
"""
Constructor.
:param velocidad: unidad de velocidad
" ""
self ._speed = velocidad
def hit_and_run ( self ) -> Ninguno :
"""
Método de plantilla
"""
self . _mover ( 'adelante' )
self . _stop ()
auto . _ataque ()
auto . _mover ( 'hacia atrás' )
@abstractmethod
def _attack ( self ) -> Ninguno :
pasar
@abstractmethod
def _stop ( auto ) -> Ninguno :
pasar
def _move ( self , dirección : str ) -> Ninguno :
"""
Movimiento: todas las unidades tienen el mismo, no incluido en la plantilla
:param dirección: dirección del movimiento
"""
self ._output ( ' mueve {} a velocidad {} ' . format ( dirección , self . _velocidad ))
def _output ( self , mensaje : str ) -> Ninguno :
"""
Método auxiliar de salida de mensajes, no incluido en la plantilla
:param mensaje: mensaje para imprimir
"""
print ( 'Escuadrón de tipo {} {} ' . format ( self . __class__ . __name__ , message ))
clase Arqueros ( Unidad ):
"""
Arqueros
"""
def _attack ( self ) -> Ninguno :
self . _output ( 'bombardea al enemigo' )
def _stop ( self ) -> Ninguno :
self . _output ( 'se detiene a 100 pies del enemigo' )
clase Soldados de caballería ( Unidad ):
"""
Soldados de caballería
"""
def _attack ( self ) -> Ninguno :
self . _output ( 'Se estrella contra la formación enemiga a todo galope' )
def _stop ( self ) -> Ninguno :
self . _output ( 'vuela hacia adelante sin detenerse' )
if __name__ == '__main__' :
print ( 'OUTPUT:' )
arqueros = arqueros ( 4 )
arqueros . hit_and_run ()
jinetes = jinetes ( 8 )
jinetes . golpea_y_corre ()
'''
SALIDA:
La unidad de tipo Arquero avanza a una velocidad de 4
La unidad de tipo Arquero se detiene a 100 pasos de un enemigo
La unidad de tipo Arquero dispara a un enemigo
La unidad de tipo Arquero retrocede a una velocidad de 4
La unidad de tipo Caballería se mueve hacia delante a una velocidad de 8
unidades de tipo Caballería vuela hacia adelante sin detenerse
unidad de tipo caballería a todo galope choca contra la formación enemiga
unidad de tipo caballería se mueve hacia atrás a una velocidad de 8
'''
Literatura
- E. Gamma, R. Helm, R. Johnson, J. Vlissides . Técnicas de diseño orientado a objetos. Patrones de Diseño = Patrones de Diseño: Elementos de Software Reutilizable Orientado a Objetos. - San Petersburgo. : "Pedro" , 2007. - S. 366. - ISBN 978-5-469-01136-1 . (también ISBN 5-272-00355-1 )
Enlaces