Ya conocemos conceptos clave como herencia y clases en Python. Ahora exploraremos un patrón de diseño muy útil en programación orientada a objetos: el método plantilla(template method).
Este patrón nos da una estructura general de cómo hacer las cosas, dejando algunos pasos para que las clases hijas los completen. En esta lección veremos cómo funciona y cómo nos ayuda a evitar duplicar código.
¿Qué es el método plantilla?
Esto se puede lograr gracias a "vinculación tardía". Suena complicado, pero la idea es simple: cuando llamamos a un método desde la clase base, Python no sabe todavía qué versión exacta del método se está ejecutando. Por eso, si una clase hija implementa su propia versión del método, esa es la versión que se va a usar.
Veámoslo paso a paso con un ejemplo real.
Ejemplo: Generar HTML con clases
Imagina que estás creando un sistema para construir elementos HTML. Sabemos que la mayoría de las etiquetas HTML tienen una forma parecida: atributo(s) + contenido + etiquetas de apertura y cierre.
Un ejemplo sencillo de etiqueta en HTML sería:
<a href="https://python.org">Enlace a Python</a>
Ahora veamos cómo podríamos representarlo con clases en Python.
1. Primer diseño: cada clase hace todo
Iniciamos con una clase específica que genera un elemento <a> (enlace):
class HTMLAnchorElement:
def __str__(self):
attr_line = self.stringify_attributes() # Método común
body = self.get_text_content() # Método común
return f'<a{attr_line}>{body}</a>'
En este código usamos dos métodos:
stringify_attributes(): arma los atributos comohref="...".get_text_content(): devuelve el texto dentro de la etiqueta.
Hasta aquí todo bien. Pero si luego queremos crear una clase para <p>, <div>, <h1>, etc., vamos a terminar copiando y pegando casi lo mismo, solo cambiando el nombre de la etiqueta.
Entonces, mejoramos el diseño.
2. Separar lo común en una clase base
Creamos una clase HtmlElement que define el método común para generar la etiqueta, y que delega a los hijos el nombre del tag:
class HtmlElement:
def __str__(self):
attr_line = self.stringify_attributes()
body = self.get_text_content()
tag_name = self.get_tag_name() # Este método se define en los hijos
return f"<{tag_name} {attr_line}>{body}</{tag_name}>"
Y ahora, las clases hijas se enfocan solo en lo que las diferencia: el nombre de la etiqueta.
class HtmlAnchorElement(HtmlElement):
def get_tag_name(self):
return "a" # Devuelve el nombre del tag
Así hacemos que str() se herede, y cada hijo se encarga solo de su parte.
Hay etiquetas en HTML que no tienen cuerpo, por ejemplo:
<hr />
<br />
<img src="image.jpg" />
Este tipo de elementos se conocen como "etiquetas individuales" (single elements). Y el código anterior, que espera que haya contenido, no funciona bien para ellos.
✅ Solución: Dividir en clases para etiquetas de apertura/cierre y etiquetas individuales
Para manejar esto, creamos dos nuevos tipos de clases que heredan de HtmlElement:
HtmlPairElement: para etiquetas con apertura y cierre.HtmlSingleElement: para etiquetas individuales.
Clase para etiquetas individuales
class HtmlSingleElement(HtmlElement):
def __str__(self):
attr_line = self.stringify_attributes()
tag_name = self.get_tag_name()
return f"<{tag_name} {attr_line} />"
Clase para etiquetas con cuerpo
class HtmlPairElement(HtmlElement):
def __str__(self):
attr_line = self.stringify_attributes()
body = self.get_text_content()
tag_name = self.get_tag_name()
return f"<{tag_name} {attr_line}>{body}</{tag_name}>"
Uso en clases hijas:
class HtmlImageElement(HtmlSingleElement):
def get_tag_name(self):
return "img"
class HtmlParagraphElement(HtmlPairElement):
def get_tag_name(self):
return "p"
De esta forma, cada clase maneja su propio tipo de etiqueta, y evitamos duplicar lógica en cada una.
¿Qué ganamos con esto?
El uso del método plantilla nos ayudó a:
- Separar lo que es común de lo que es específico.
- Organizar mejor nuestro código.
- Reducir repeticiones en clases hijas.
- Hacer que nuestro código sea más fácil de mantener.
Veamos una comparación final.
| Elemento HTML | Descripción / Tipo |
|---|---|
HtmlElement |
Base — Lógica general |
HtmlSingleElement |
Subclase — Formato de etiqueta individual |
HtmlPairElement |
Subclase — Formato de etiqueta con cuerpo |
HtmlAnchorElement |
Especialización — get_tag_name() |
HtmlImageElement |
Especialización — get_tag_name() |
Resumen
- El patrón método plantilla permite definir una estructura común en una clase base, y delegar los detalles a clases hijas.
- Se apoya en el mecanismo de vinculación tardía de Python, que decide qué método ejecutar en tiempo de ejecución.
- Aplicamos este patrón creando una clase base
HtmlElement, con métodos que llaman a otros métodos que se definen en las clases hijas. - Para adaptar el comportamiento a diferentes tipos de etiquetas HTML, usamos subclases como
HtmlSingleElementyHtmlPairElement. - Evitar código duplicado hace que nuestro programa sea más claro, limpio y fácil de mantener.
Para acceder completo a curso necesitas un plan básico
El plan básico te dará acceso completo a todos los cursos, ejercicios y lecciones de Códica, proyectos y acceso de por vida a la teoría de las lecciones completadas. La suscripción se puede cancelar en cualquier momento.