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

class Amplifier:
    """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

class HomeTheaterFacade:
    """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

def main():
    # 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

"Avatar"
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

class DatabaseFacade:
    """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

class FileProcessorFacade:
    """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.
Otras extensiones