En la programación orientada a objetos , el método de plantilla es uno de los patrones de diseño de comportamiento identificados por Gamma et al. [1] en el libro Design Patterns . El método de plantilla es un método en una superclase, generalmente una superclase abstracta, y define el esqueleto de una operación en términos de una serie de pasos de alto nivel. Estos pasos se implementan ellos mismos mediante métodos auxiliares adicionales en la misma clase que el método de plantilla .
Los métodos auxiliares pueden ser métodos abstractos , en cuyo caso se requieren subclases para proporcionar implementaciones concretas, o métodos de enlace , que tienen cuerpos vacíos en la superclase. Las subclases pueden (pero no es obligatorio) personalizar la operación anulando los métodos de enlace. La intención del método de plantilla es definir la estructura general de la operación, al tiempo que permite que las subclases refinen o redefinan ciertos pasos. [2]
Descripción general
Este patrón tiene dos partes principales:
- El "método de plantilla" se implementa como un método en una clase base (generalmente una clase abstracta ). Este método contiene código para las partes del algoritmo general que son invariantes. La plantilla asegura que siempre se siga el algoritmo general. [1] En el método de plantilla, las partes del algoritmo que pueden variar se implementan mediante el envío de mensajes propios que solicitan la ejecución de métodos auxiliares adicionales . En la clase base, estos métodos auxiliares reciben una implementación predeterminada, o ninguna en absoluto (es decir, pueden ser métodos abstractos).
- Las subclases de la clase base "completan" las partes vacías o "variantes" de la "plantilla" con algoritmos específicos que varían de una subclase a otra. [3] Es importante que las subclases no anulen el método de plantilla en sí.
En tiempo de ejecución, el algoritmo representado por el método de plantilla se ejecuta enviando el mensaje de plantilla a una instancia de una de las subclases concretas. A través de la herencia, el método de plantilla en la clase base comienza a ejecutarse. Cuando el método de plantilla envía un mensaje a uno mismo solicitando uno de los métodos auxiliares, el mensaje será recibido por la subinstancia concreta. Si se ha anulado el método auxiliar, se ejecutará la implementación anulada en la subinstancia; si no se ha anulado, se ejecutará la implementación heredada en la clase base. Este mecanismo asegura que el algoritmo general siga los mismos pasos cada vez, al tiempo que permite que los detalles de algunos pasos dependan de qué instancia recibió la solicitud original para ejecutar el algoritmo.
Este patrón es un ejemplo de inversión de control porque el código de alto nivel ya no determina qué algoritmos ejecutar; en su lugar, se selecciona un algoritmo de nivel inferior en tiempo de ejecución.
Algunos de los mensajes propios enviados por el método de plantilla pueden ser métodos de enganche. Estos métodos se implementan en la misma clase base que el método de plantilla, pero con cuerpos vacíos (es decir, no hacen nada). Los métodos de enlace existen para que las subclases puedan anularlos y, por lo tanto, puedan ajustar la acción del algoritmo sin la necesidad de anular el método de plantilla en sí. En otras palabras, proporcionan un "gancho" en el que "colgar" las implementaciones variantes.
Estructura
Diagrama de clases UML
En el diagrama de clases de UML anterior , AbstractClass
define una templateMethod()
operación que define el esqueleto (plantilla) de un comportamiento por
- implementar las partes invariantes del comportamiento y
- enviarse a sí mismo los mensajes
primitive1()
yprimitive2()
que, debido a que están implementadosSubClass1
, permiten que esa subclase proporcione una implementación variante de esas partes del algoritmo.
Uso
El método de plantilla se utiliza en marcos, donde cada uno implementa las partes invariantes de la arquitectura de un dominio, al tiempo que proporciona métodos de enganche para la personalización. Este es un ejemplo de inversión de control . El método de la plantilla se utiliza por las siguientes razones. [3]
- Permite que las subclases implementen un comportamiento variable (mediante la anulación de los métodos de enlace). [6]
- Evita la duplicación en el código: el flujo de trabajo general del algoritmo se implementa una vez en el método de plantilla de la clase abstracta, y las variaciones necesarias se implementan en las subclases. [6]
- Controla los puntos en los que se permite la especialización. Si las subclases simplemente reemplazaran el método de la plantilla, podrían realizar cambios radicales y arbitrarios en el flujo de trabajo. Por el contrario, al anular solo los métodos de enlace, solo se pueden cambiar ciertos detalles específicos del flujo de trabajo, [6] y el flujo de trabajo general se deja intacto.
Usar con generadores de código
El patrón de plantilla es útil cuando se trabaja con código generado automáticamente. El desafío de trabajar con código generado es que los cambios en el código fuente conducirán a cambios en el código generado; si se han realizado modificaciones escritas a mano en el código generado, estas se perderán. Entonces, ¿cómo se debe personalizar el código generado?
El patrón de plantilla proporciona una solución. Si el código generado sigue el patrón del método de plantilla, todo el código generado será una superclase abstracta. Siempre que las personalizaciones escritas a mano se limiten a una subclase, el generador de código se puede ejecutar de nuevo sin riesgo de sobrescribir estas modificaciones. Cuando se utiliza con la generación de código, este patrón a veces se denomina patrón de brecha generacional . [7]
Ejemplo de PHP
Resumen de clase Juego { abstracta protegida función initialize (); función protegida abstracta startPlay (); función protegida abstracta endPlay (); / ** Método de plantilla * / función final pública play () { / ** Primitiva * / $ this -> initialize (); / ** Primitivo * / $ this -> startPlay (); / ** Primitivo * / $ this -> endPlay (); } }clase Mario extiende el juego { función protegida initialize () { echo "¡Juego de Mario inicializado! Empieza a jugar". , PHP_EOL ; } función protegida startPlay () { echo "Comenzó el juego de Mario. ¡Disfruta el juego!" , PHP_EOL ; } función protegida endPlay () { echo "¡Juego de Mario terminado!" , PHP_EOL ; }}class Tankfight extiende el juego { función protegida initialize () { echo "¡Juego de Tankfight inicializado! Empieza a jugar". , PHP_EOL ; } función protegida startPlay () { echo "Se inició el juego Tankfight. ¡Disfruta el juego!" , PHP_EOL ; } función protegida endPlay () { echo "¡Juego de peleas de tanques terminado!" , PHP_EOL ; }}$ juego = nuevo Tankfight (); $ juego -> jugar ();$ juego = nuevo Mario (); $ juego -> jugar ();
Ver también
Referencias
- ^ a b Gamma, Erich ; Helm, Richard ; Johnson, Ralph ; Vlissides, John (1994). "Método de plantilla". Patrones de diseño . Addison-Wesley. págs. 325–330 . ISBN 0-201-63361-2.
- ^ Freeman, Eric; Freeman, Elisabeth; Sierra, Kathy; Bates, Bert (2004). Hendrickson, Mike; Loukides, Mike (eds.). Head First Design Patterns (rústica) . 1 . O'REILLY. págs. 289, 311. ISBN 978-0-596-00712-6. Consultado el 12 de septiembre de 2012 .
- ^ a b "Patrón de diseño de método de plantilla" . Source Making - profesional de la enseñanza de TI . Consultado el 12 de septiembre de 2012 .
El método de plantilla se utiliza de forma destacada en los marcos.
- ^ "El patrón de diseño del método de plantilla - Estructura" . w3sDesign.com . Consultado el 12 de agosto de 2017 .
- ^ Leyenda de LePUS3. Obtenido de http://lepus.org.uk/ref/legend/legend.xml .
- ^ a b c Chung, Carlo (2011). Patrones de diseño Pro Objective-C para iOS . Berkeley, CA: Apress. pag. 266. ISBN 978-1-4302-3331-2.
- ^ Vlissides, John (22 de junio de 1998). Tramado de patrones: patrones de diseño aplicados . Addison-Wesley Professional. págs. 85-101. ISBN 978-0201432930.
enlaces externos
- Seis usos comunes del patrón de plantilla
- Trabajar con clases de plantillas en PHP 5
- Patrón de diseño de método de plantilla