Parcial 5: Aplicando patrones de diseño, Enunciado y Resuelto en PYthon by Yuscu Mejia
Ejercicio: Implementación del Patrón Observer
Introducción
Actualmente, Yuscu Mejía tiene un sistema estructurado como Facebook que permite manejar notificaciones entre personas y grupos de manera centralizada. Este sistema tiene las siguientes funcionalidades:
- Personas pueden seguir a otras personas: Cuando una persona publica algo, todas las personas que la siguen reciben una notificación con su nombre, el mensaje publicado y una URL donde pueden ver el contenido.
- Personas pueden seguir a grupos: Cuando un grupo publica algo, todas las personas que siguen al grupo reciben una notificación con el nombre del grupo, el mensaje publicado y una URL donde pueden ver el contenido.
- Operaciones de seguimiento y notificaciones:
- Puedes agregar o quitar observadores (seguidores) tanto a personas como a grupos.
- Puedes publicar mensajes desde personas o grupos, y el sistema enviará las notificaciones adecuadas.
Problema Actual
El código actual usa listas globales y estructuras condicionales (if) para manejar las relaciones entre personas y grupos, así como para enviar notificaciones. Este enfoque presenta las siguientes malas prácticas:
- Falta de encapsulamiento: Toda la lógica para agregar, quitar y notificar está dispersa y no organizada en clases.
- Escalabilidad limitada: Agregar nuevas funcionalidades o tipos de publicadores/observadores requiere modificar varias partes del código.
- Mantenimiento difícil: Las listas globales pueden generar errores si no se manejan correctamente.
- No sigue principios de diseño: No utiliza un patrón de diseño claro lo que podría mejorar la organización y reutilización del código.
Ejercicio
Debes tomar el sistema estructurado existente y refactorizarlo para implementar el Patrón de Diseño Observer. Esto implica crear una solución donde:
- Las clases principales sean
PersonayGrupo. - Se implemente la relación entre publicadores y observadores utilizando el patrón Observer.
- Se encapsule la lógica de notificaciones dentro de las clases correspondientes.
Código Inicial
# Lista global para manejar observadores
observadores_persona = {}
observadores_grupo = {}
def agregar_observador(tipo, nombre, observador):
if tipo == "persona":
if nombre not in observadores_persona:
observadores_persona[nombre] = []
observadores_persona[nombre].append(observador)
elif tipo == "grupo":
if nombre not in observadores_grupo:
observadores_grupo[nombre] = []
observadores_grupo[nombre].append(observador)
def remover_observador(tipo, nombre, observador):
if tipo == "persona":
if nombre in observadores_persona:
observadores_persona[nombre].remove(observador)
elif tipo == "grupo":
if nombre in observadores_grupo:
observadores_grupo[nombre].remove(observador)
def notificar_observadores(tipo, nombre, mensaje, url):
if tipo == "persona":
if nombre in observadores_persona:
for observador in observadores_persona[nombre]:
print(f"Notificación para {observador}: {nombre} publicó: '{mensaje}'. Míralo aquí: {url}")
elif tipo == "grupo":
if nombre in observadores_grupo:
for observador in observadores_grupo[nombre]:
print(f"Notificación para {observador}: El grupo {nombre} publicó: '{mensaje}'. Míralo aquí: {url}")
def publicar_persona(nombre, mensaje, url):
print(f"{nombre} publicó: {mensaje}")
notificar_observadores("persona", nombre, mensaje, url)
def publicar_grupo(nombre, mensaje, url):
print(f"El grupo {nombre} publicó: {mensaje}")
notificar_observadores("grupo", nombre, mensaje, url)
# Ejemplo de uso
# Crear personas y grupos
nombre_alice = "Alice"
nombre_bob = "Bob"
nombre_carol = "Carol"
nombre_grupo_desarrolladores = "Desarrolladores"
# Alice sigue a Bob y al grupo Desarrolladores
agregar_observador("persona", nombre_bob, nombre_alice)
agregar_observador("grupo", nombre_grupo_desarrolladores, nombre_alice)
# Bob sigue al grupo Desarrolladores
agregar_observador("grupo", nombre_grupo_desarrolladores, nombre_bob)
# Carol sigue a Bob
agregar_observador("persona", nombre_bob, nombre_carol)
# Bob publica algo
publicar_persona(nombre_bob, "¡Mira mi nueva entrada en el blog!", "http://example.com/blog")
# El grupo Desarrolladores publica algo
publicar_grupo(nombre_grupo_desarrolladores, "¡Tenemos un nuevo evento!", "http://example.com/event")
Solución
# Refactorizado utilizando el Patrón Observer
from abc import ABC, abstractmethod
class Observador(ABC):
"""Interfaz para los observadores."""
@abstractmethod
def actualizar(self, nombre_publicador, mensaje, url):
pass
class Publicador(ABC):
"""Interfaz para los publicadores."""
def __init__(self):
self._observadores = []
def agregar_observador(self, observador):
self._observadores.append(observador)
def remover_observador(self, observador):
self._observadores.remove(observador)
def notificar_observadores(self, mensaje, url):
for observador in self._observadores:
observador.actualizar(self.name, mensaje, url)
class Persona(Publicador, Observador):
"""Clase que representa a una persona que puede publicar y observar."""
def __init__(self, name):
super().__init__()
self.name = name
def publicar(self, mensaje, url):
print(f"{self.name} publicó: {mensaje}")
self.notificar_observadores(mensaje, url)
def actualizar(self, nombre_publicador, mensaje, url):
print(f"Notificación para {self.name}: {nombre_publicador} publicó: '{mensaje}'. Míralo aquí: {url}")
class Grupos(Publicador):
"""Clase que representa a un grupo que puede publicar."""
def __init__(self, name):
super().__init__()
self.name = name
def publicar(self, mensaje, url):
print(f"Grupo {self.name} publicó: {mensaje}")
self.notificar_observadores(mensaje, url)
# Ejemplo de uso
# Crear personas
alice = Persona("Alice")
bob = Persona("Bob")
carol = Persona("Carol")
# Crear un grupo
desarrolladores_grupo = Grupos("Desarrolladores")
# Alice sigue a Bob y al grupo Desarrolladores
bob.agregar_observador(alice)
desarrolladores_grupo.agregar_observador(alice)
# Bob sigue al grupo Desarrolladores
desarrolladores_grupo.agregar_observador(bob)
# Carol sigue a Bob
bob.agregar_observador(carol)
# Bob publica algo
bob.publicar("¡Mira mi nueva entrada en el blog!", "http://example.com/blog")
# El grupo Desarrolladores publica algo
desarrolladores_grupo.publicar("¡Tenemos un nuevo evento!", "http://example.com/event")
Práctica
Te invito a ver el resuelto de este ejercicio en nuestro canal de YouTube:
Recorda si te gusta los videos, te agradeceria si le pones un comentario o un like para saber si subir mas videos! 😮
Si no sabes que comentar, comenta con: estoy avanzando rapido con el curso de Programacion python 🙂 asi te detectaremos que viniste de aca, para una estadistica si conviene o no subir videos

