Menu
Coddy logo textTech

Patrón Abstract Factory

Parte de la sección Programación Orientada a Objetos del Journey de GO de Coddy — lección 88 de 107.

El patrón Abstract Factory extiende el patrón Factory mediante la creación de familias de objetos relacionados sin especificar sus tipos concretos. En lugar de una única función de fábrica, se define una interfaz de fábrica que implementan múltiples fábricas concretas, cada una de las cuales produce un conjunto consistente de objetos relacionados.

Considera un kit de herramientas de interfaz de usuario (UI toolkit) que necesita crear botones y casillas de verificación. Los diferentes sistemas operativos requieren implementaciones distintas, pero los componentes deben funcionar juntos de manera consistente:

type Button interface {
    Render() string
}

type Checkbox interface {
    Check() string
}

// Interfaz de fábrica abstracta
type GUIFactory interface {
    CreateButton() Button
    CreateCheckbox() Checkbox
}

Cada fábrica concreta produce una familia de componentes relacionados:

// Familia Windows
type WindowsButton struct{}
func (w WindowsButton) Render() string { return "Windows Button" }

type WindowsCheckbox struct{}
func (w WindowsCheckbox) Check() string { return "Windows Checkbox" }

type WindowsFactory struct{}
func (w WindowsFactory) CreateButton() Button { return WindowsButton{} }
func (w WindowsFactory) CreateCheckbox() Checkbox { return WindowsCheckbox{} }

// Familia Mac
type MacButton struct{}
func (m MacButton) Render() string { return "Mac Button" }

type MacCheckbox struct{}
func (m MacCheckbox) Check() string { return "Mac Checkbox" }

type MacFactory struct{}
func (m MacFactory) CreateButton() Button { return MacButton{} }
func (m MacFactory) CreateCheckbox() Checkbox { return MacCheckbox{} }

El código cliente trabaja con la interfaz de la fábrica, manteniéndose independiente de las implementaciones concretas:

func BuildUI(factory GUIFactory) {
    button := factory.CreateButton()
    checkbox := factory.CreateCheckbox()
    fmt.Println(button.Render(), checkbox.Check())
}

Usa Abstract Factory cuando tu sistema necesite trabajar con múltiples familias de productos relacionados y quieras asegurar que los componentes de la misma familia se utilicen juntos. Es más complejo que un Factory simple, así que recurre a él solo cuando realmente necesites gestionar familias de productos.

challenge icon

Desafío

Fácil

¡Vamos a construir un sistema de tienda de muebles utilizando el patrón Abstract Factory! Crearás fábricas que producen familias de artículos de mobiliario relacionados; cada fábrica produce un estilo consistente (Moderno o Vintage), asegurando que las sillas y mesas de la misma fábrica combinen estéticamente.

Organizarás tu código en tres archivos:

  • furniture.go: Define tus interfaces de producto y tipos de muebles concretos.

    Crea dos interfaces de producto:

    • Chair con un método SitOn() string
    • Table con un método PlaceItems() string

    Implementa dos familias de muebles:

    • Familia Modern: ModernChair devuelve "Sitting on a sleek modern chair" y ModernTable devuelve "Placing items on a glass modern table"
    • Familia Vintage: VintageChair devuelve "Sitting on an ornate vintage chair" y VintageTable devuelve "Placing items on a wooden vintage table"
  • factory.go: Define tu interfaz de fábrica abstracta y fábricas concretas.

    Crea una interfaz FurnitureFactory con dos métodos:

    • CreateChair() Chair
    • CreateTable() Table

    Implementa dos fábricas concretas:

    • ModernFactory que produce ModernChair y ModernTable
    • VintageFactory que produce VintageChair y VintageTable

    También crea una función GetFactory(style string) FurnitureFactory que devuelva la fábrica adecuada basada en el estilo ("modern" o "vintage"). Por defecto, usa ModernFactory para estilos no reconocidos.

  • main.go: Usa tus fábricas para amueblar habitaciones.

    Crea una función FurnishRoom(factory FurnitureFactory) string que utilice la fábrica para crear una silla y una mesa, y luego devuelva una cadena formateada que muestre ambas acciones en líneas separadas.

    Lee una entrada de estilo, obtén la fábrica adecuada, amuebla una habitación e imprime el resultado.

Se proporcionarán las siguientes entradas:

  • Línea 1: Estilo de mueble ("modern", "vintage", u otro)

Por ejemplo, dado:

modern

Tu salida debería ser:

Sitting on a sleek modern chair
Placing items on a glass modern table

Y dado:

vintage

Tu salida debería ser:

Sitting on an ornate vintage chair
Placing items on a wooden vintage table

Y dado:

rustic

Tu salida debería ser:

Sitting on a sleek modern chair
Placing items on a glass modern table

Observa cómo la función FurnishRoom funciona con cualquier fábrica a través de la interfaz; no sabe si está creando muebles modernos o vintage. ¡Esto asegura que todos los muebles de una habitación provengan de la misma familia, manteniendo un estilo consistente!

Hoja de referencia

El patrón Abstract Factory crea familias de objetos relacionados sin especificar sus tipos concretos. Define una interfaz de fábrica que implementan múltiples fábricas concretas, cada una produciendo un conjunto consistente de objetos relacionados.

Estructura

Defina interfaces de producto para cada tipo de objeto:

type Button interface {
    Render() string
}

type Checkbox interface {
    Check() string
}

Cree una interfaz de fábrica abstracta que declare métodos para crear cada tipo de producto:

type GUIFactory interface {
    CreateButton() Button
    CreateCheckbox() Checkbox
}

Implementaciones Concretas

Implemente familias de productos concretas donde cada familia tenga un estilo o comportamiento consistente:

// Familia Windows
type WindowsButton struct{}
func (w WindowsButton) Render() string { return "Windows Button" }

type WindowsCheckbox struct{}
func (w WindowsCheckbox) Check() string { return "Windows Checkbox" }

type WindowsFactory struct{}
func (w WindowsFactory) CreateButton() Button { return WindowsButton{} }
func (w WindowsFactory) CreateCheckbox() Checkbox { return WindowsCheckbox{} }

// Familia Mac
type MacButton struct{}
func (m MacButton) Render() string { return "Mac Button" }

type MacCheckbox struct{}
func (m MacCheckbox) Check() string { return "Mac Checkbox" }

type MacFactory struct{}
func (m MacFactory) CreateButton() Button { return MacButton{} }
func (m MacFactory) CreateCheckbox() Checkbox { return MacCheckbox{} }

Código del Cliente

El código del cliente trabaja con la interfaz de la fábrica, permaneciendo independiente de las implementaciones concretas:

func BuildUI(factory GUIFactory) {
    button := factory.CreateButton()
    checkbox := factory.CreateCheckbox()
    fmt.Println(button.Render(), checkbox.Check())
}

Cuándo usarlo

Use Abstract Factory cuando su sistema necesite trabajar con múltiples familias de productos relacionados y desee asegurarse de que los componentes de la misma familia se utilicen juntos. Es más complejo que una Factory simple, así que úselo solo cuando realmente necesite gestionar familias de productos.

Pruébalo tú mismo

package main

import "fmt"

// FurnishRoom utiliza una fábrica para crear muebles y devuelve el resultado
// TODO: Implementar esta función
// - Usar la fábrica para crear una silla y una mesa
// - Devolver una cadena con el resultado de SitOn() en la primera línea y el de PlaceItems() en la segunda
func FurnishRoom(factory FurnitureFactory) string {
	// TODO: Crear silla y mesa usando la fábrica
	// TODO: Devolver la cadena formateada con ambas acciones en líneas separadas
	return ""
}

func main() {
	var style string
	fmt.Scanln(&style)

	// TODO: Obtener la fábrica adecuada basada en el estilo
	// TODO: Amueblar una habitación usando la fábrica
	// TODO: Imprimir el resultado
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos