Patrón Fachada en Python
El patrón fachada (Facade Pattern) es un patrón de diseño estructural que proporciona una interfaz simplificada para subsistemas complejos. Imagina que vas a un restaurante a comer: no necesitas conocer todos los detalles de cómo el chef corta, cocina y emplata en la cocina; solo tienes que decirle al camarero qué quieres comer, y el camarero coordinará todo el trabajo en la cocina. Este camarero desempeña el papel de la 'fachada'.
En el desarrollo de software, el patrón fachada oculta la complejidad del subsistema creando una interfaz unificada, lo que facilita el uso del código del cliente.
La idea central del patrón fachada
Simplificar sistemas complejos
Cuando el sistema se vuelve cada vez más complejo, las dependencias entre clases también se vuelven intrincadas. El patrón fachada reduce el acoplamiento entre el sistema y el cliente al proporcionar una interfaz de alto nivel.
Proporcionar una entrada unificada
La clase fachada actúa como la única entrada al subsistema; el cliente solo necesita interactuar con la clase fachada, sin necesidad de conocer la compleja estructura interna del subsistema.
Reducir el umbral de uso
Para los desarrolladores que no están familiarizados con la estructura interna del sistema, el patrón fachada les permite empezar a usar rápidamente las funciones del sistema.
La estructura del patrón fachada

Como se puede ver en el diagrama:
- Client (cliente): código que utiliza la clase fachada
- Facade (clase fachada): proporciona una interfaz simplificada y coordina los distintos subsistemas
- Subsystem (clase de subsistema): clases que implementan funciones concretas
Ejemplo de aplicación real: sistema de cine en casa
Entendamos la aplicación práctica del patrón fachada mediante un ejemplo de cine en casa.
Clases de subsistema
Primero, creamos las clases de los distintos dispositivos del cine en casa:
Ejemplo
"""Clase amplificador"""
def on(self):
print("Amplificador encendido")
def set_volume(self, level):
print(f"Volumen establecido en {level}")
def off(self):
print("Amplificador apagado")
class DVDPlayer:
"""Clase reproductor de DVD"""
def on(self):
print("Reproductor de DVD encendido")
def play(self, movie):
print(f"Reproduciendo película: {movie}")
def stop(self):
print("Reproductor de DVD detenido")
def off(self):
print("Reproductor de DVD apagado")
class Projector:
"""Clase proyector"""
def on(self):
print("Proyector encendido")
def set_input(self, source):
print(f"Fuente de entrada del proyector establecida en: {source}")
def off(self):
print("Proyector apagado")
class Lights:
"""Clase Luces"""
def dim(self, level):
print(f"Luces atenuadas al {level}%")
def on(self):
print("Luces completamente encendidas")
class Screen:
"""Clase Pantalla"""
def down(self):
print("Pantalla bajada")
def up(self):
print("Pantalla subida")
Clase fachada
Ahora creamos la clase fachada, que encapsula las operaciones complejas de todos los dispositivos:
Ejemplo
"""Clase fachada de cine en casa"""
def __init__(self):
self.amplifier = Amplifier()
self.dvd_player = DVDPlayer()
self.projector = Projector()
self.lights = Lights()
self.screen = Screen()
def watch_movie(self, movie):
"""Ver la película: realiza todos los preparativos con un solo clic"""
print("\n=== Iniciar modo cine en casa ===)
# Encender los dispositivos en el orden correcto
self.lights.dim(10) # Atenuar las luces
self.screen.down() # Bajar la pantalla
self.projector.on() # Encender el proyector
self.projector.set_input("DVD")
self.amplifier.on() # Encender el amplificador
self.amplifier.set_volume(5) # Ajustar el volumen
self.dvd_player.on() # Encender el reproductor de DVD
self.dvd_player.play(movie) # Reproducir la película
print("=== Cine en casa listo ===\n")
def end_movie(self):
"""Terminar de ver la película: apaga todos los dispositivos con un solo clic"""
print("\n=== Finalizar modo cine en casa ===)
# Apagar los dispositivos en el orden correcto
self.dvd_player.stop() # Detener el DVD
self.dvd_player.off() # Apagar el DVD
self.amplifier.off() # Apagar el amplificador
self.projector.off() # Apagar el proyector
self.screen.up() # Subir la pantalla
self.lights.on() # Encender las luces
print("=== Todos los dispositivos apagados ===\n")
Código del cliente
Ahora veamos cómo el cliente usa esta interfaz simplificada:
Ejemplo
# Crear una instancia de la fachada de cine en casa
home_theater = HomeTheaterFacade()
# Ver la película - ¡solo hay que llamar a un método!
home_theater.watch_movie("Avatar")
# Simular el proceso de ver la película...
print("Disfrutando de la película...\n")
# Terminar de ver la película - ¡también solo hay que llamar a un método!
home_theater.end_movie()
if __name__ == "__main__":
main()
Resultado de ejecución:
=== 开始家庭影院模式 === 灯光调暗到 10% 屏幕已降下 投影仪已开启 投影仪输入源设置为: DVD 功放已开启 音量设置为 5 DVD播放器已开启 开始播放电影: 阿凡达 === 家庭影院准备就绪 === 正在享受电影时光... === 结束家庭影院模式 === DVD播放器已停止 DVD播放器已关闭 功放已关闭 投影仪已关闭 屏幕已升起 灯光全开 === 所有设备已关闭 ===
Ventajas del patrón fachada
1. Simplificar el código del cliente
Ejemplo
Ejemplo
def watch_movie_manual():
lights = Lights()
screen = Screen()
projector = Projector()
amplifier = Amplifier()
dvd_player = DVDPlayer()
lights.dim(10)
screen.down()
projector.on()
projector.set_input("DVD")
amplifier.on()
amplifier.set_volume(5)
dvd_player.on()
dvd_player.play(# Usar el patrón fachada - código de cliente simplificado)
"Avatar"
def watch_movie_simple():
home_theater = HomeTheaterFacade()
home_theater.watch_movie(2. Reducir el acoplamiento)
2. Reducir el acoplamiento
3. Mejorar la mantenibilidad del código
3. Mejorar la mantenibilidad del código
Más escenarios de aplicación real
Más escenarios de aplicación real
Escenario 1: fachada para operaciones de base de datos
Ejemplo
"""Interfaz simplificada para ejecutar consultas"""
def __init__(self, connection_string):
self.connection_string = connection_string
def execute_query(self, query, params=None):
# Conectar a la base de datos
# Ejecutar consulta
connection = self._connect()
cursor = connection.cursor()
try:
# Obtener resultados
if params:
cursor.execute(query, params)
else:
cursor.execute(query)
"Error al ejecutar la consulta: {e}"
result = cursor.fetchall()
return result
except Exception as e:
print(f# Cerrar la conexión)
return None
finally:
"""Método de conexión interno - oculto al cliente"""
cursor.close()
connection.close()
def _connect(self):
# La lógica real de conexión a la base de datos
Conectando a la base de datos...
print(Simular la conexión a la base de datos)
return Escenario 2: fachada para procesamiento de archivos
Escenario 2: fachada para procesamiento de archivos
Ejemplo
"""Interfaz simplificada para procesar archivos"""
def process_file(self, file_path):
# Validar archivo
try:
# Leer archivo
if not self._validate_file(file_path):
return False
# Procesar contenido
content = self._read_file(file_path)
# Guardar resultado
processed_content = self._process_content(content)
Error al procesar el archivo: {e}
self._save_result(processed_content)
return True
except Exception as e:
print(f"""Validar archivo""")
return False
def _validate_file(self, file_path):
Validar archivo: {file_path}
print(f"""Leer archivo""")
return True
def _read_file(self, file_path):
Leer archivo: {file_path}
print(fContenido del archivo)
return """Procesar contenido"""
def _process_content(self, content):
Procesando contenido del archivo...
print(Contenido procesado)
return """Guardar resultado"""
def _save_result(self, content):
Guardando el resultado del procesamiento...
print(Mejores prácticas del patrón fachada)
Mejores prácticas del patrón fachada
1. Diseñar la interfaz de manera razonable
2. Mantener una responsabilidad única
2. Mantener una responsabilidad única
3. No usar en exceso
3. No usar en exceso
4. Considerar la extensibilidad
4. Considerar la extensibilidad
Ejercicios prácticos
Ejercicios prácticos
Ejercicio 1: mejorar el sistema de cine en casa
Ejercicio 1: mejorar el sistema de cine en casa
ParaHomeTheaterFacadeMétodo: encender solo el sistema de audio para escuchar música
listen_to_music(song)Método: activar el modo de juego (puede requerir una configuración de dispositivos diferente)play_game(game)Método: activar el modo de juego (puede requerir una configuración de dispositivo diferente)
Ejercicio 2: crear una fachada para el procesamiento de pedidos de comercio electrónico
Diseñar una fachada de procesamiento de pedidos para un sistema de comercio electrónico, que incluya los siguientes subsistemas:
- Verificación de inventario
- Procesamiento de pagos
- Organización logística
- Notificación por correo electrónico
Ejercicio 3: técnicas de depuración
Agregue una función de registro en la clase de fachada para registrar la hora y los parámetros de cada llamada a método, lo que facilita la depuración.
Resumen
El patrón de fachada es una herramienta poderosa que oculta la complejidad del sistema al proporcionar una interfaz simplificada. Al igual que un camarero en un restaurante, la clase de fachada actúa como intermediario entre el cliente y los subsistemas, haciendo que el uso de sistemas complejos sea simple e intuitivo.
Puntos clave:
- El patrón de fachada reduce la complejidad de uso del sistema.
- Mejora la mantenibilidad y legibilidad del código.
- Reduce el acoplamiento entre el cliente y los subsistemas.
- Es especialmente adecuado para sistemas complejos o bibliotecas que necesitan proporcionar una API simplificada.