Patrón de Plantilla

En el patrón de plantilla (Template Pattern), una clase abstracta define públicamente la forma/plantilla para ejecutar sus métodos. Sus subclases pueden sobrescribir la implementación de los métodos según sea necesario, pero la invocación se realizará de la manera definida en la clase abstracta. Este tipo de patrón de diseño pertenece a los patrones de comportamiento.

Introducción

Intención

Define el esqueleto de un algoritmo en la clase padre y permite que las subclases redefinan ciertos pasos específicos del algoritmo sin cambiar su estructura.

Problema principal que resuelve

  • Resuelve el problema de implementar repetidamente los mismos métodos en múltiples subclases, evitando la duplicación de código al abstraer los métodos comunes en la clase padre.

Escenarios de uso

  • Cuando existen métodos comunes que pueden compartirse entre varias subclases.

Forma de implementación

  • Definir la clase padre abstracta: contiene el método plantilla y algunos métodos abstractos o concretos.
  • Implementar las subclases: heredan de la clase padre abstracta e implementan los métodos abstractos sin cambiar la estructura del algoritmo.

Código clave

  • Método plantilla: se define en la clase padre abstracta y llama a métodos abstractos y concretos.
  • Métodos abstractos: implementados por las subclases, representan la parte variable del algoritmo.
  • Métodos concretos: implementados en la clase padre abstracta, representan la parte invariable del algoritmo.

Ejemplos de aplicación

  • Proceso de construcción: pasos como los cimientos, el cableado y las tuberías son iguales; pasos posteriores como añadir armarios empotrados o vallas son diferentes.
  • Los 81 desastres de Viaje al Oeste: los 81 desastres definidos por la bodhisattva representan un esqueleto lógico de alto nivel.
  • El soporte de Spring para Hibernate: encapsula métodos comunes como abrir transacciones, obtener Session y cerrar Session.

Ventajas

  • Encapsula la parte invariable: la parte invariable del algoritmo se encapsula en la clase padre.
  • Extiende la parte variable: las subclases pueden extender o modificar la parte variable del algoritmo.
  • Extrae código común: reduce la duplicación de código y facilita el mantenimiento.

Desventajas

  • Aumento del número de clases: cada implementación diferente requiere una subclase, lo que puede hacer que el sistema sea grande.

Recomendaciones de uso

  • Cuando varias subclases tengan métodos comunes con la misma lógica, considere usar el patrón de método plantilla.
  • Para métodos importantes o complejos, se puede considerar definirlos como métodos plantilla en la clase padre.

Notas

  • Para evitar modificaciones malintencionadas, el método plantilla generalmente se modifica con lafinalpalabra clave, evitando que sea sobrescrito por las subclases.

Los principales roles involucrados

  • Clase padre abstracta (Abstract Class):

    • Define el método plantilla y algunos métodos abstractos o concretos.
  • Subclases concretas (Concrete Classes):

    • Heredan de la clase padre abstracta e implementan los métodos abstractos.
  • Método gancho (Hook Method) (opcional):

    • Se define en la clase padre abstracta y puede ser sobrescrito por las subclases para afectar el comportamiento del método plantilla.
  • Cliente (Client) (opcional):

    • Utiliza la clase padre abstracta y las subclases concretas sin preocuparse por los detalles del método plantilla.

Implementación

Vamos a crear unaGameclase abstracta que define operaciones, donde el método plantilla se establece como final, de modo que no pueda ser sobrescrito.CricketyFootballson las clases de entidadGameque extienden la clase abstracta y sobrescriben sus métodos.

TemplatePatternDemo, nuestra clase de demostración usaGamepara demostrar el uso del patrón de plantilla.

模板模式的 UML 图

Paso 1

Crear una clase abstracta cuyo método plantilla se establece como final.

Game.java

public abstract class Game { abstract void initialize(); abstract void startPlay(); abstract void endPlay(); //Plantilla public final void play(){ //Inicializar el juego initialize(); //Iniciar el juego startPlay(); //Finalizar el juego endPlay(); } }

Paso 2

Crear las clases de entidad que extienden la clase anterior.

Cricket.java

public class Cricket extends Game { @Override void endPlay() { System.out.println("Cricket Game Finished!"); } @Override void initialize() { System.out.println("Cricket Game Initialized! Start playing."); } @Override void startPlay() { System.out.println("Cricket Game Started. Enjoy the game!"); } }

Football.java

public class Football extends Game { @Override void endPlay() { System.out.println("Football Game Finished!"); } @Override void initialize() { System.out.println("Football Game Initialized! Start playing."); } @Override void startPlay() { System.out.println("Football Game Started. Enjoy the game!"); } }

Paso 3

UsarGameel método plantilla play() para demostrar la forma en que se define el juego.

TemplatePatternDemo.java

public class TemplatePatternDemo { public static void main(String[] args) { Game game = new Cricket(); game.play(); System.out.println(); game = new Football(); game.play(); } }

Paso 4

Ejecutar el programa y ver el resultado:

Cricket Game Initialized! Start playing.
Cricket Game Started. Enjoy the game!
Cricket Game Finished!

Football Game Initialized! Start playing.
Football Game Started. Enjoy the game!
Football Game Finished!
Otras extensiones