-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #15 from sivanahamer/template-method
Se realiza pull request del Template method al main
- Loading branch information
Showing
17 changed files
with
330 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# Template Method | ||
|
||
<div align="center"> | ||
|
||
[![Typing SVG](https://readme-typing-svg.herokuapp.com?font=Cabin&duration=2500&pause=250&color=388CF7&background=1914FF00¢er=true&vCenter=true&width=300&height=75&lines=Patr%C3%B3n+Template+Method)](https://git.io/typing-svg) | ||
|
||
</div> | ||
|
||
## Contenidos | ||
|
||
1. [Definición](./content/Definicion.md) | ||
2. [Estructura Básica](./content/Estructura.md) | ||
3. [Problema](./content/Problema.md) | ||
4. [Solución](./content/Solucion.md) | ||
5. [Código UCR](./src/Cursos.py) | ||
6. [Código Bebidas](./src/Bebida.py) | ||
7. [Consecuencias](./content/Consecuencias.md) | ||
8. [Implementación](./content/Implementacion.md) | ||
9. [Relación con otros patrones](./content/Patrones_Relacionados.md) | ||
10. [Referencias](./content/Referencias.md) | ||
|
||
Para ver un resumen de los contenidos diríjase a la siguiente [presentación](./presentation/Template%20Method.pdf) | ||
|
||
## About | ||
|
||
Todo el contenido fue elaborado por: | ||
* Gabriel González Flores. C03376. Gabriel.gonzalezflores@ucr.ac.cr | ||
* Lizeth Corrales Cortés. C02428. Lizeth.corrales@ucr.ac.cr |
17 changes: 17 additions & 0 deletions
17
docs/5.patterns/comportamiento/template-method/content/Consecuencias.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Consecuencias | ||
## Ventajas | ||
* Puede permitir que los clientes anulen solo ciertas partes de un algoritmo grande, de modo que se vean menos afectados por los cambios que ocurren en otras partes del algoritmo. | ||
* Puede extraer el código duplicado en una superclase. | ||
* Cumple el principio DRY al evitar la duplicación de código. | ||
|
||
(Shvets, A, 2019, p.392) | ||
|
||
## Desventajas | ||
* Algunos clientes pueden estar limitados por el esqueleto proporcionado por un algoritmo. | ||
* Puede violar el principio de Liskov Substitución al suprimir la implementación de un paso predeterminada a través de una subclase. | ||
* Los métodos plantilla tienden a ser más difíciles de mantener cuantos más pasos tienen. | ||
|
||
(Shvets, A, 2019, p.392) | ||
|
||
|
||
[Regresar al Readme](./../README.md) |
8 changes: 8 additions & 0 deletions
8
docs/5.patterns/comportamiento/template-method/content/Definicion.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# Template Method | ||
Es un patrón de diseño de comportamiento en el que se define el esqueleto o la base de un algoritmo en la superclase, pero dando la posibilidad a las subclases que creen sus propias implementaciones del algoritmo sin cambiar su estructura. | ||
|
||
Por lo que, puede ser utilizado cuando se desea permitir a los clientes extender únicamente pasos particulares de un algoritmo, pero no todo el algoritmo o su estructura, así como cuando se poseen muchas clases con algoritmos casi idénticos, pero con algunas diferencias mínimas, de modo que se presente la necesidad de modificar todas las clases cuando el algoritmo cambie. | ||
|
||
(Shvets, A, 2019, p.381) | ||
|
||
[Regresar al Readme](../README.md) |
14 changes: 14 additions & 0 deletions
14
docs/5.patterns/comportamiento/template-method/content/Estructura.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Estructura Básica | ||
## Elementos participantes | ||
* Clase abstracta: | ||
- Declara métodos que actúan como pasos de un algoritmo, así como el método de plantilla (template method) real que llama a estos métodos en un orden específico. | ||
- Los pasos pueden declararse abstractos o tener alguna implementación predeterminada. | ||
* Clases concretas: | ||
- Pueden sobreescribir todos los pasos, pero no el método plantilla en sí. | ||
|
||
(Shvets, A, 2019, p.386-387) | ||
|
||
|
||
![Imagen Estructura básica](./../img/Estructura_Template_Method.png) | ||
|
||
[Regresar al Readme](./../README.md) |
14 changes: 14 additions & 0 deletions
14
docs/5.patterns/comportamiento/template-method/content/Implementacion.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Implementación | ||
Para implementar el patrón Bridge debemos tener en cuenta las siguientes sugerencias y técnicas. | ||
|
||
- Analizar el algoritmo que tenemos como objetivo para identificar si puede ser dividido en pasos, considerar qué pasos son comunes para todas las clases concretas y cuáles serán únicos, es decir, que deben ser implementados por la misma clase concreta. | ||
- Crear la clase base abstracta y declarar el método plantilla dentro de esta clase base abstracta, además se debe definir dentro del método plantilla los métodos que representan los pasos dentro del algoritmo, creando de esta manera la estructura que se va a seguir. | ||
- No está mal que todos los pasos del algoritmo sean abstractos, sin embargo, es mejor definir los pasos que pueden tener una implementación por defecto, ya que las clases concretas no deberán implementar tantos pasos. | ||
- Para cada variación que se pueda dar dentro del algoritmo dependiendo de la situación se debe crear una nueva clase concreta, esta debe implementar los pasos abstractos y podría sobrescribir los pasos definidos de antemano. | ||
- Analizar el algoritmo que tenemos como objetivo para identificar si puede ser dividido en pasos, considerar qué pasos son comunes para todas las clases concretas y cuáles serán únicos | ||
- Crear la clase base abstracta y declarar el método plantilla dentro de esta clase base abstracta | ||
- Para cada variación que se pueda dar dentro del algoritmo dependiendo de la situación, se debe crear una nueva clase concreta, esta debe implementar los pasos abstractos y podría sobrescribir los pasos definidos de antemano. | ||
|
||
(Refactoring.guru, s.f.) | ||
|
||
[Regresar al Readme](./../README.md) |
16 changes: 16 additions & 0 deletions
16
docs/5.patterns/comportamiento/template-method/content/Patrones_Relacionados.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Patrones Relacionados | ||
## Strategy | ||
* Semejante al Template Method excepto en su granularidad. | ||
* Template Method utiliza la herencia para variar parte de un algoritmo | ||
* Strategy utiliza la delegación para variar todo el algoritmo. | ||
* Strategy modifica la lógica de los objetos individuales, mientras que Template Method modifica la lógica de una clase completa. | ||
|
||
(Shvets, A, 2019, p.392) | ||
|
||
## Factory Method | ||
Es una especialización del Template Method. Al mismo tiempo, un método de fábrica puede servir como un paso en un método de plantilla grande. | ||
|
||
(Shvets, A, 2019, p.392) | ||
|
||
|
||
[Regresar al Readme](./../README.md) |
30 changes: 30 additions & 0 deletions
30
docs/5.patterns/comportamiento/template-method/content/Problema.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Problema | ||
|
||
### **¿Cuándo tiene sentido utilizar el patrón Bridge?** | ||
|
||
El patrón Template Method tiene sentido utilizarlo cuando se desee que un cliente pueda extender únicamente algunos pasos de un algoritmo, pero siempre siguiendo una misma estructura. Por medio de este patrón se puede identificar un algoritmo monolítico y separarlo en varios pasos que se pueden extender en diferentes clases concretas. | ||
|
||
Por otra parte, este patrón resulta útil cuando se identifican muchas clases con algoritmos casi idénticos, pero que se diferencian en muy pocos pasos, por lo tanto, cuando se convierte un algoritmo en un método plantilla, entonces se pueden encapsular dichos pasos con implementaciones similares a una superclase. | ||
|
||
|
||
Vamos a definir dos ejemplos que ayudará a visualizar su utilidad, uno relacionado con bebidas calientes y un problema relacionado dentro de un contexto de la UCR: | ||
|
||
### **Problema de bebidas calientes** | ||
|
||
Digamos que se tiene un restaurante donde se sirven bebidas calientes, para preparar estas bebidas calientes se debe seguir algunos pasos que se repiten para varias bebidas calientes, pero otros pasos son completamente únicos. El problema es que para cada bebida caliente se está repitiendo mucho código y es difícil implementar una nueva bebida caliente, es por esto que se opta por el patrón de diseño Template Method. | ||
|
||
![Ejemplo_Bebidas_Calientes_Solas](./../img/Clases_Bebidas_Calientes.png) | ||
|
||
A continuación puede visualizar la [solución](./Solucion.md/#solución-para-problema-de-las-bebidas-calientes) al problema descrito | ||
|
||
### **Problema dentro de un contexto de la UCR** | ||
|
||
Dentro de Mediación Virtual, a lo largo del año, se crean muchos entornos para diferentes cursos, ya sean de ingeniería, derecho, artes, etc; como se puede suponer, al momento de crear estos entornos para los distintos cursos se tendría que generar código que puede ser diferente para cada entorno o por lo contrario, bastante similar, esto puede ser contraproducente si no se maneja correctamente, ya que se puede llegar a tener mucho código duplicado y puede llegar a complicarse, si no se tiene una estructura definida. | ||
|
||
En este sentido, se obtendrá el siguiente resultado, en donde se define un curso de matemática, computación e inglés que no dependen de ninguna clase, pero que no poseen una estructura definida. | ||
|
||
![Ejemplo_UCR_Sin_Bridge](./../img/Clases_Cursos_UCR.PNG) | ||
|
||
A continuación puede visualizar la [solución](./Solucion.md/#solución-para-problema-de-la-ucr) al problema descrito | ||
|
||
[Regresar al Readme](./../README.md) |
7 changes: 7 additions & 0 deletions
7
docs/5.patterns/comportamiento/template-method/content/Referencias.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# Referencias | ||
|
||
Refactoring.guru. (s.f.) Template Method. https://refactoring.guru/es/design-patterns/template-method | ||
|
||
Shvets, A (2019) Dive Into Design Patterns. | ||
|
||
[Regresar al Readme](./../README.md) |
23 changes: 23 additions & 0 deletions
23
docs/5.patterns/comportamiento/template-method/content/Solucion.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Solución | ||
|
||
### **Solución para problema de las bebidas calientes** | ||
Para generar una solución más óptima al [problema de las bebidas calientes](./Problema.md/#problema-de-bebidas-calientes) podemos utilizar el patrón Template Method, ya que permitirá definir una estructura para cada bebida caliente, definiendo de antemano varios métodos que se utilizan para todas las bebidas calientes, así evitando la redundancia código y que de esta manera cada nueva bebida caliente que se quiere implementar sea más fácil de agregar y solo deberá definir pocos métodos únicos. | ||
|
||
![Template_Bebidas_Calientes](./../img/Template_Bebidas_Calientes.png) | ||
|
||
Para observar un ejemplo de implementación diríjase al siguiente [código](./../src/Bebida.py) | ||
|
||
### **Solución para problema de la UCR** | ||
Para generar una solución más óptima al [problema de la UCR](./Problema.md/#problema-dentro-de-un-contexto-de-la-ucr) podemos utilizar el patrón de comportamiento Template Method, ya que se logrará definir una estructura por medio de pasos para todos los cursos que sean creados en un futuro y evitar redundancia de código al declarar e implementar los métodos que son utilizados por todos los cursos en una clase en común. | ||
|
||
Por lo que, siguiendo lo definido por este patrón, es necesario crear una clase abstracta denominada curso que contiene métodos como CrearCurso(), AsignarSigla(), AsignarSemestreAño(), AsignarProfes(), CrearPlantillaPlataforma(), InscribirEstudiantes() y AsignarAsistente(). | ||
|
||
El método CrearCurso() será el método plantilla que va a definir la estructura de la creación de cursos. | ||
|
||
Con respecto a los métodos AsignarSigla(), AsignarSemestreAño(), AsignarProfes() , InscribirEstudiantes() y AsignarAsistente(), estos van a ser implementados para evitar la repetición de código, además se tiene al método CrearPlantillaCurso(), el cual será abstracto, lo cual implica que la plantilla del curso debe ser implementada cada vez que se cree una nueva clase concreta. | ||
|
||
![Template_Cursos_UCR](./../img/Template_Cursos_UCR.PNG) | ||
|
||
Para observar un ejemplo de implementación diríjase al siguiente [código](./../src/Cursos.py) | ||
|
||
[Regresar al Readme](./../README.md) |
Binary file added
BIN
+149 KB
docs/5.patterns/comportamiento/template-method/img/Clases_Bebidas_Calientes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+24.5 KB
docs/5.patterns/comportamiento/template-method/img/Clases_Cursos_UCR.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+211 KB
docs/5.patterns/comportamiento/template-method/img/Estructura_Template_Method.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+129 KB
docs/5.patterns/comportamiento/template-method/img/Template_Bebidas_Calientes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+72.2 KB
docs/5.patterns/comportamiento/template-method/img/Template_Cursos_UCR.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+1.12 MB
docs/5.patterns/comportamiento/template-method/presentation/Template Method.pdf
Binary file not shown.
59 changes: 59 additions & 0 deletions
59
docs/5.patterns/comportamiento/template-method/src/Bebida.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
from abc import ABC, abstractmethod | ||
|
||
class Bebida(ABC): | ||
|
||
# Método plantilla | ||
# Define la estructura del algoritmo | ||
def preparar(self) -> None: | ||
self.hervir_agua() # Paso 1 | ||
self.preparar_bebida() # Paso 2 (Abstracto) | ||
self.verter_bebida() # Paso 3 | ||
self.agregar_ingredientes() # Paso 4 (Abstracto) | ||
|
||
# Estos pasos ya tienen implementaciones. | ||
|
||
def hervir_agua(self) -> None: | ||
print("Se está hirviendo el agua...") | ||
|
||
def verter_bebida(self) -> None: | ||
print("Se está vertiendo la bebida...") | ||
|
||
# Estos pasos deben ser implementados por las clases concretas. | ||
|
||
@abstractmethod | ||
def preparar_bebida(self) -> None: | ||
pass | ||
|
||
@abstractmethod | ||
def agregar_ingredientes(self) -> None: | ||
pass | ||
|
||
class Café(Bebida): | ||
|
||
def preparar_bebida(self) -> None: | ||
print("Se está preparando el café...") | ||
|
||
def agregar_ingredientes(self) -> None: | ||
print("Agregando azúcar y leche al café...") | ||
|
||
|
||
class Té(Bebida): | ||
|
||
def preparar_bebida(self) -> None: | ||
print("Se están remojando las bolsitas de té...") | ||
|
||
def agregar_ingredientes(self) -> None: | ||
print("Agregando miel al té...") | ||
|
||
|
||
def client_code(bebida: Bebida) -> None: | ||
bebida.preparar() | ||
|
||
if __name__ == "__main__": | ||
print("Se pidió un café") | ||
client_code(Café()) | ||
print("\n") | ||
|
||
print("Se pidió un té") | ||
client_code(Té()) | ||
print("\n") |
114 changes: 114 additions & 0 deletions
114
docs/5.patterns/comportamiento/template-method/src/Cursos.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
from abc import ABC, abstractmethod | ||
|
||
class CursoAbstracto(ABC): | ||
|
||
def __init__(self): | ||
self.nombreCurso = "" | ||
self.sigla = "" | ||
self.grupo = 0 | ||
self.cicloCurso = "" | ||
self.profes = [] | ||
self.estudiantes = [] | ||
self.asistente = "" | ||
|
||
# Método plantilla | ||
# Define la estructura del algoritmo | ||
def CrearCurso(self) -> None: | ||
self.AsignarNombreCurso() # Paso 1 | ||
self.AsignarSigla() # Paso 2 | ||
self.AsignarGrupo() # Paso 3 | ||
self.AsignarCicloCurso() # Paso 4 | ||
self.AsignarProfes() # Paso 5 | ||
self.CrearPlantillaCurso() # Paso 6 (Abstracto) | ||
self.InscribirEstudiantes() # Paso 7 | ||
|
||
tieneAsistente = input("¿El curso " + self.nombreCurso + " contará con un asistente? (si o no): ") | ||
tieneAsistente = tieneAsistente.lower() | ||
|
||
if(tieneAsistente == "si" or tieneAsistente == "sí"): | ||
self.AsignarAsistente # Paso 8 | ||
|
||
# Estos pasos ya tienen implementaciones. | ||
|
||
def AsignarNombreCurso(self) -> None: | ||
self.nombreCurso = input("Ingrese el nombre del curso: ") | ||
print("Se asignó el nombre de curso", self.nombreCurso,".\n") | ||
|
||
def AsignarSigla(self) -> None: | ||
self.sigla = input("Ingrese la sigla del curso: ") | ||
print("Se asignó la sigla", self.sigla, "al curso", self.nombreCurso,".\n") | ||
|
||
def AsignarGrupo(self) -> None: | ||
self.grupo = input("Ingrese el grupo del curso: ") | ||
print("Se asignó el grupo", self.grupo, "al curso", self.nombreCurso,".\n") | ||
|
||
def AsignarCicloCurso(self) -> None: | ||
self.cicloCurso = input("Ingrese el ciclo del curso (Ej: I 2023): ") | ||
print("Se asignó el ciclo del curso", self.cicloCurso, "al curso", self.nombreCurso, ".\n") | ||
|
||
def AsignarProfes(self) -> None: | ||
listaProfes = input("Ingrese el nombre del profesor. Si son varios profesores se deben separar con comas: ") | ||
self.profes = listaProfes.split(",") | ||
listaProfes = ", ".join(self.profes) | ||
print("Se asignaron los profesores\n", listaProfes, "\nal curso", self.nombreCurso, ".\n") | ||
|
||
def InscribirEstudiantes(self) -> None: | ||
listaEstudiantes = input("Ingrese el nombre de los estudiantes. Se deben separar con comas: ") | ||
self.estudiantes = listaEstudiantes.split(",") | ||
listaEstudiantes = ", ".join(self.estudiantes) | ||
print("Se asignaron los estudiantes\n", listaEstudiantes, "\nal curso", self.nombreCurso, ".\n") | ||
|
||
def AsignarAsistente(self) -> None: | ||
asistente = input("Ingrese el nombre de la/el asistente: ") | ||
self.asistente = asistente | ||
print("Se asignó la/el asistente", self.asistente, "al curso", self.nombreCurso, ".\n") | ||
|
||
# Este paso deben ser implementado por las clases concretas. | ||
|
||
abstractmethod | ||
def CrearPlantillaCurso(self) -> None: | ||
pass | ||
|
||
class CursoMatematica(CursoAbstracto): | ||
|
||
def CrearPlantillaCurso(self) -> None: | ||
print("Escogiendo Interfaz Oscura") | ||
print("Creando sección de Información") | ||
print("Creando sección de Tareas") | ||
print("Creando plantilla específica para el curso", self.nombreCurso, "...\n") | ||
|
||
class CursoComputacion(CursoAbstracto): | ||
|
||
def CrearPlantillaCurso(self) -> None: | ||
print("Escogiendo Interfaz Clara") | ||
print("Creando sección de Material del Curso") | ||
print("Creando sección de Tareas") | ||
print("Creando sección de Proyectos") | ||
print("Creando sección de Laboratorios") | ||
print("Creando plantilla específica para el curso", self.nombreCurso, "...\n") | ||
|
||
class CursoIngles(CursoAbstracto): | ||
|
||
def CrearPlantillaCurso(self) -> None: | ||
print("Escogiendo Interfaz Oscura") | ||
print("Creando sección de Material del Curso") | ||
print("Creando sección de Material Complementario") | ||
print("Creando sección de Proyectos") | ||
print("Creando plantilla específica para el curso", self.nombreCurso, "...\n") | ||
|
||
|
||
def client_code(curso: CursoAbstracto) -> None: | ||
curso.CrearCurso() | ||
|
||
if __name__ == "__main__": | ||
print("Creando el curso de Matemáticas") | ||
client_code(CursoMatematica()) | ||
print("\n") | ||
|
||
print("Creando el curso de Computación") | ||
client_code(CursoComputacion()) | ||
print("\n") | ||
|
||
print("Creando el curso de Inglés") | ||
client_code(CursoIngles()) | ||
print("\n") |