Lección 8.5: Patron de diseño Builder
Patrón de Diseño Builder en Python
Introducción
¡Hola a todos! Soy Yuscu Mejía y en esta lección vamos a explorar el concepto del patrón de diseño Builder en Python. El patrón Builder separa la construcción de un objeto complejo de su representación, permitiendo que el mismo proceso de construcción pueda crear diferentes representaciones.
Características
El patrón Builder en Python tiene las siguientes características:
- Permite construir objetos paso a paso.
- Separa la construcción de un objeto complejo de su representación.
- El mismo proceso de construcción puede crear diferentes representaciones.
Propósito
El patrón de diseño Builder permite construir un objeto complejo paso a paso. Permite crear diferentes tipos y representaciones de un objeto utilizando el mismo proceso de construcción.
Problema
El problema que resuelve el patrón Builder es la necesidad de crear un objeto complejo de manera controlada y detallada, especialmente cuando el proceso de creación implica múltiples pasos y variaciones.
Solución
La solución propuesta por el patrón Builder es separar el proceso de construcción del objeto de su representación, utilizando un Builder para realizar la construcción paso a paso y un Director para dirigir el proceso.
Analogía en el Mundo Real
Una analogía del mundo real sería la construcción de una casa. Se siguen diferentes pasos para construir una casa (cimientos, paredes, techo, etc.), y dependiendo de las necesidades del cliente, se pueden construir diferentes tipos de casas (casa de campo, casa moderna, etc.).
Estructura
La estructura del patrón Builder incluye los siguientes componentes:
- Builder: Declara una interfaz para crear partes de un objeto Product.
- ConcreteBuilder: Implementa la interfaz Builder y construye partes concretas del objeto Product.
- Product: Representa el objeto complejo que se está construyendo.
- Director: Construye un objeto utilizando la interfaz Builder.

Aplicabilidad
El patrón Builder es aplicable cuando:
- Se requiere construir una representación compleja de un objeto paso a paso.
- Se desea que el proceso de construcción permita crear diferentes representaciones del objeto.
- El proceso de construcción de un objeto implica múltiples pasos que deben ser realizados en un orden específico.
Pros y Contras
- Pros:
- Permite construir objetos complejos paso a paso.
- Facilita la creación de diferentes representaciones de un objeto utilizando el mismo código de construcción.
- Promueve la separación de preocupaciones al dividir el proceso de construcción en diferentes clases.
- Contras:
- Puede introducir complejidad adicional debido a la creación de múltiples clases y métodos.
- El proceso de construcción puede ser menos eficiente si no se optimiza adecuadamente.
Vamos a ver el uso del Patrón Builder
A continuación, un ejemplo de cómo utilizar el patrón Builder en Python, presentado por Yuscu Mejía:
- Patrón Builder:
# Definir el producto complejo
class Producto:
def __init__(self):
self.partes = []
def agregar(self, parte):
self.partes.append(parte)
def listar_partes(self):
return ", ".join(self.partes)
# Definir la interfaz Builder
class Builder:
def construir_parte_a(self):
pass
def construir_parte_b(self):
pass
def obtener_producto(self):
pass
# Definir el ConcreteBuilder
class ConcreteBuilder(Builder):
def __init__(self):
self.reset()
def reset(self):
self._producto = Producto()
def construir_parte_a(self):
self._producto.agregar("Parte A")
def construir_parte_b(self):
self._producto.agregar("Parte B")
def obtener_producto(self):
producto = self._producto
self.reset()
return producto
# Definir el Director
class Director:
def __init__(self, builder: Builder = None):
self._builder = builder
def establecer_builder(self, builder: Builder):
self._builder = builder
def construir_producto_completo(self):
if self._builder is None:
raise ValueError("Builder no está definido")
self._builder.construir_parte_a()
self._builder.construir_parte_b()
def construir_producto_personalizado(self, partes):
if self._builder is None:
raise ValueError("Builder no está definido")
for parte in partes:
if parte == 'A':
self._builder.construir_parte_a()
elif parte == 'B':
self._builder.construir_parte_b()
# Ejemplo de uso
if __name__ == "__main__":
builder = ConcreteBuilder()
director = Director(builder)
print("Construyendo un producto completo:")
director.construir_producto_completo()
producto = builder.obtener_producto()
print(producto.listar_partes())
print("Construyendo un producto personalizado:")
director.construir_producto_personalizado(['A'])
producto = builder.obtener_producto()
print(producto.listar_partes())
Práctica
Para practicar, les invito a ver nuestro tutorial en video sobre el patrón de diseño Builder en Python, presentado por Yuscu Mejía:
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

Ejercicio
Ahora les propongo un ejercicio para aplicar lo que hemos aprendido sobre el patrón de diseño Builder en Python, con la guía de Yuscu Mejía:
Ejercicio: Implementar el Patrón Builder para Construir Computadoras
Vamos a crear una clase llamada Computadora que represente el producto complejo. Definiremos una interfaz BuilderComputadora y dos clases concretas BuilderComputadoraOficina y BuilderComputadoraJuegos que implementen esta interfaz. También crearemos una clase DirectorComputadora para dirigir el proceso de construcción.
#Ejercicio
# Definir la clase Producto (Computadora)
class Computadora:
def __init__(self):
self.partes = []
def agregar_parte(self, parte):
self.partes.append(parte)
def mostrar_partes(self):
print(f"Partes de la computadora: {', '.join(self.partes)}")
# Definir la interfaz Builder
from abc import ABC, abstractmethod
class BuilderComputadora(ABC):
@abstractmethod
def construir_procesador(self):
pass
@abstractmethod
def construir_memoria(self):
pass
@abstractmethod
def construir_almacenamiento(self):
pass
@abstractmethod
def obtener_computadora(self):
pass
# Definir ConcreteBuilder para Computadora de Oficina
class BuilderComputadoraOficina(BuilderComputadora):
def __init__(self):
self.computadora = Computadora()
def construir_procesador(self):
self.computadora.agregar_parte("Procesador i5")
def construir_memoria(self):
self.computadora.agregar_parte("8GB RAM")
def construir_almacenamiento(self):
self.computadora.agregar_parte("256GB SSD")
def obtener_computadora(self):
return self.computadora
# Definir ConcreteBuilder para Computadora de Juegos
class BuilderComputadoraJuegos(BuilderComputadora):
def __init__(self):
self.computadora = Computadora()
def construir_procesador(self):
self.computadora.agregar_parte("Procesador i7")
def construir_memoria(self):
self.computadora.agregar_parte("16GB RAM")
def construir_almacenamiento(self):
self.computadora.agregar_parte("1TB SSD")
def obtener_computadora(self):
return self.computadora
# Definir la clase Director
class DirectorComputadora:
def __init__(self, builder: BuilderComputadora):
self.builder = builder
def construir_computadora_completa(self):
self.builder.construir_procesador()
self.builder.construir_memoria()
self.builder.construir_almacenamiento()
def obtener_computadora(self):
return self.builder.obtener_computadora()
# Ejemplo de uso
if __name__ == "__main__":
# Construir una computadora de oficina
builder_oficina = BuilderComputadoraOficina()
director = DirectorComputadora(builder_oficina)
director.construir_computadora_completa()
computadora_oficina = director.obtener_computadora()
computadora_oficina.mostrar_partes()
# Construir una computadora de juegos
builder_juegos = BuilderComputadoraJuegos()
director = DirectorComputadora(builder_juegos)
director.construir_computadora_completa()
computadora_juegos = director.obtener_computadora()
computadora_juegos.mostrar_partes()

