Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save LaChivaloca69/c1dee4f6d81382ce9cb3c2297d9cedc0 to your computer and use it in GitHub Desktop.

Select an option

Save LaChivaloca69/c1dee4f6d81382ce9cb3c2297d9cedc0 to your computer and use it in GitHub Desktop.

Alvarado Cardona Antonio 22210279

Código Refactorizado con Patrones GoF

using System;
using System.Collections.Generic;

namespace GranjaInteligente
{
    //  FACTORY METHOD
    // Creamos una clase abstracta para Dieta
    public abstract class Dieta
    {
        public abstract void Alimentar();
    }

    // Implementaciones concretas de dieta por animal
    public class DietaVaca : Dieta
    {
        public override void Alimentar()
        {
            Console.WriteLine("Dando heno, agua y sal mineral a la vaca.");
        }
    }

    public class DietaCerdo : Dieta
    {
        public override void Alimentar()
        {
            Console.WriteLine("Dando granos y jugo al cerdo.");
        }
    }

    public class DietaGallina : Dieta
    {
        public override void Alimentar()
        {
            Console.WriteLine("Dando semillas y agua a la gallina.");
        }
    }

    // Factory Method: clase base
    public abstract class DietaFactory
    {
        public abstract Dieta CrearDieta();
    }

    // Factorías concretas
    public class DietaVacaFactory : DietaFactory
    {
        public override Dieta CrearDieta() => new DietaVaca();
    }

    public class DietaCerdoFactory : DietaFactory
    {
        public override Dieta CrearDieta() => new DietaCerdo();
    }

    public class DietaGallinaFactory : DietaFactory
    {
        public override Dieta CrearDieta() => new DietaGallina();
    }

    //  ABSTRACT FACTORY
    // Familia de productos: Alimento, Bebida, Suplemento
    public interface IAlimento { void Mostrar(); }
    public interface IBebida { void Mostrar(); }
    public interface ISuplemento { void Mostrar(); }

    // Productos concretos para Vaca
    public class Heno : IAlimento { public void Mostrar() => Console.WriteLine("Alimento: Heno"); }
    public class Agua : IBebida { public void Mostrar() => Console.WriteLine("Bebida: Agua"); }
    public class SalMineral : ISuplemento { public void Mostrar() => Console.WriteLine("Suplemento: Sal mineral"); }

    // Productos concretos para Cerdo
    public class Granos : IAlimento { public void Mostrar() => Console.WriteLine("Alimento: Granos"); }
    public class Jugo : IBebida { public void Mostrar() => Console.WriteLine("Bebida: Jugo"); }
    public class SuplementoCerdo : ISuplemento { public void Mostrar() => Console.WriteLine("Suplemento: Vitaminas porcinas"); }

    // Productos concretos para Gallina
    public class Semillas : IAlimento { public void Mostrar() => Console.WriteLine("Alimento: Semillas"); }
    public class AguaGallina : IBebida { public void Mostrar() => Console.WriteLine("Bebida: Agua fresca"); }
    public class Calcio : ISuplemento { public void Mostrar() => Console.WriteLine("Suplemento: Calcio"); }

    // Abstract Factory
    public interface IAnimalFactory
    {
        IAlimento CrearAlimento();
        IBebida CrearBebida();
        ISuplemento CrearSuplemento();
    }

    // Factorías concretas
    public class VacaFactory : IAnimalFactory
    {
        public IAlimento CrearAlimento() => new Heno();
        public IBebida CrearBebida() => new Agua();
        public ISuplemento CrearSuplemento() => new SalMineral();
    }

    public class CerdoFactory : IAnimalFactory
    {
        public IAlimento CrearAlimento() => new Granos();
        public IBebida CrearBebida() => new Jugo();
        public ISuplemento CrearSuplemento() => new SuplementoCerdo();
    }

    public class GallinaFactory : IAnimalFactory
    {
        public IAlimento CrearAlimento() => new Semillas();
        public IBebida CrearBebida() => new AguaGallina();
        public ISuplemento CrearSuplemento() => new Calcio();
    }

    // BUILDER
    public class RutinaAlimentacion
    {
        public List<string> Pasos { get; set; } = new List<string>();

        public void MostrarRutina()
        {
            Console.WriteLine("=== Rutina de alimentación ===");
            foreach (var paso in Pasos)
                Console.WriteLine(paso);
        }
    }

    public interface IRutinaBuilder
    {
        void PrepararDesayuno();
        void PrepararSnack();
        void PrepararCena();
        RutinaAlimentacion ObtenerRutina();
    }

    public class RutinaVacaBuilder : IRutinaBuilder
    {
        private RutinaAlimentacion rutina = new RutinaAlimentacion();

        public void PrepararDesayuno() => rutina.Pasos.Add("Desayuno: Heno + Agua");
        public void PrepararSnack() => rutina.Pasos.Add("Snack: Sal Mineral");
        public void PrepararCena() => rutina.Pasos.Add("Cena: Heno + Agua");
        public RutinaAlimentacion ObtenerRutina() => rutina;
    }

    public class RutinaDirector
    {
        public RutinaAlimentacion Construir(IRutinaBuilder builder)
        {
            builder.PrepararDesayuno();
            builder.PrepararSnack();
            builder.PrepararCena();
            return builder.ObtenerRutina();
        }
    }

    //  PROTOTYPE
    public class RutinaPrototype : ICloneable
    {
        public RutinaAlimentacion? Rutina { get; set; }

        public object Clone()
        {
            return new RutinaPrototype
            {
                Rutina = new RutinaAlimentacion { Pasos = new List<string>(Rutina!.Pasos) }
            };
        }
    }

    //  SINGLETON THREAD-SAFE
    public class RegistroGlobalAlimentacion
    {
        private static readonly object _lock = new object();
        private static RegistroGlobalAlimentacion? instancia;

        private RegistroGlobalAlimentacion() { }

        public static RegistroGlobalAlimentacion Instancia
        {
            get
            {
                if (instancia == null)
                {
                    lock (_lock)
                    {
                        if (instancia == null)
                            instancia = new RegistroGlobalAlimentacion();
                    }
                }
                return instancia;
            }
        }

        public void Registrar(string mensaje)
        {
            Console.WriteLine($"[REGISTRO] {mensaje}");
        }
    }

    //  MAIN PROGRAM
    public class Program
    {
        public static void Main(string[] args)
        {
            // FACTORY METHOD
            DietaFactory dietaFactory = new DietaVacaFactory();
            var dieta = dietaFactory.CrearDieta();
            dieta.Alimentar();

            // ABSTRACT FACTORY
            IAnimalFactory factory = new VacaFactory();
            factory.CrearAlimento().Mostrar();
            factory.CrearBebida().Mostrar();
            factory.CrearSuplemento().Mostrar();

            // BUILDER
            var director = new RutinaDirector();
            var rutinaBuilder = new RutinaVacaBuilder();
            var rutina = director.Construir(rutinaBuilder);
            rutina.MostrarRutina();

            // PROTOTYPE
            var prototipo = new RutinaPrototype { Rutina = rutina };
            var rutinaClonada = (RutinaPrototype)prototipo.Clone();
            rutinaClonada.Rutina!.MostrarRutina();

            // SINGLETON
            var registro = RegistroGlobalAlimentacion.Instancia;
            registro.Registrar("Ciclo de alimentación completado.");
        }
    }
}

Cambios Realizados

Factory Method (reemplaza FeedingSystem) Antes: if/else gigante en FeedingSystem. Ahora: Cada dieta se crea con su propia factoría (DietaVacaFactory, DietaCerdoFactory, DietaGallinaFactory).

Abstract Factory Antes: No existía separación de familias de productos. Ahora: IAnimalFactory produce familias consistentes (Alimento, Bebida, Suplemento).

Builder Antes: No había construcción paso a paso de rutinas. Ahora: RutinaDirector construye rutinas completas con RutinaVacaBuilder.

Prototype Antes: Cada rutina debía configurarse manualmente. Ahora: Se pueden clonar rutinas previas (RutinaPrototype) para ahorrar configuración.

Singleton (corregido) Antes: RegistroAlimentacion no era thread-safe. Ahora: RegistroGlobalAlimentacion usa double-checked locking para seguridad en multihilo.

Problemas del Código Original

Uso de if/else rígido en FeedingSystem

  • El método Alimentar(string animal) dependía de cadenas de texto.
  • Si había un error tipográfico ("vaca" en minúscula, por ejemplo), no funcionaba.
  • Violaba el principio OCP (Open/Closed Principle): cada nuevo animal obligaba a modificar la clase.
  • No existía encapsulación de la lógica de alimentación por animal.

Singleton mal implementado (RegistroAlimentacion)

  • No era thread-safe: en entornos concurrentes podían crearse varias instancias.
  • No había bloqueo (lock) ni control de acceso simultáneo.
  • Violaba el SRP (Single Responsibility Principle): mezclaba lógica de creación con registro de logs.

Falta de separación de responsabilidades

  • Toda la lógica estaba embebida en unas pocas clases.
  • No había abstracciones para representar dietas, alimentos, bebidas o suplementos.
  • Esto dificultaba la extensión del sistema (ej. agregar caballos, ovejas, etc.).

No existía abstracción para familias de productos

  • Los alimentos, bebidas y suplementos estaban “hardcodeados” dentro de strings.
  • Si se quisiera cambiar qué consume cada animal, había que modificar código en lugar de extenderlo.

Ausencia de un mecanismo para crear rutinas

  • No existía un patrón de construcción paso a paso (Builder).
  • Las rutinas de alimentación estaban implícitas en Console.WriteLine, sin posibilidad de reusarlas o configurarlas dinámicamente.

No se podían reutilizar configuraciones exitosas

  • No había un Prototype para clonar rutinas previas.
  • Cada rutina debía escribirse de cero aunque fuera muy similar a otra.

Link de grabacion asciinema

https://asciinema.org/a/x0a1HJQtKD0qorO7higAsy1Ti

@IoTeacher
Copy link

💬 Retroalimentación – Antonio
Práctica: Granja Creacional (Patrones de Diseño Creacionales – GoF)
Calificación: 85 / 100
Buen trabajo, Antonio. Se nota un esfuerzo claro por comprender y aplicar los patrones creacionales en el contexto de una granja automatizada.
Tu código incluye implementaciones correctas de Factory Method, Abstract Factory, Builder, Prototype y Singleton, lo cual cumple de forma completa con los requisitos de la práctica.
Además, es positivo que incluyas comentarios sobre los cambios realizados y problemas del código original, mostrando reflexión sobre el proceso de diseño.
Como primera práctica, el resultado es muy bueno. Para futuras entregas, podrías mejorar en:
Integrar los patrones en un flujo funcional más cohesivo.
Incluir más documentación interna (comentarios sobre decisiones de diseño).
Agregar validaciones o pruebas que demuestren el funcionamiento con distintos escenarios.
En general, se cumple el objetivo principal: entender y aplicar los patrones creacionales de manera práctica y estructurada.
Sigue con este nivel de detalle, solo reforzando la explicación técnica y la integración entre componentes.
Puntaje final: 85 / 100

10 puntos con el agregado Asciinema da 95..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment