Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save Sh0cko/e68650420a44bbbf944cae707cdd09f7 to your computer and use it in GitHub Desktop.

Select an option

Save Sh0cko/e68650420a44bbbf944cae707cdd09f7 to your computer and use it in GitHub Desktop.

Práctica Integral: Sistema de Alimentación Automatizada para Granja Inteligente

Refactorización con Patrones Creacionales GoF

Joel Cuevas Estrada - 22210298


Identificación de Problemas en el Código Inicial

  1. FeedingSystem rígido y acoplado:

    • Usa condicionales if/else para cada animal.
    • Difícil de extender cuando se agregan nuevos animales.
  2. Falta de separación de responsabilidades:

    • FeedingSystem maneja lógica de negocio y detalle de menú al mismo tiempo.
  3. RegistroAlimentacion con Singleton inseguro:

    • No es thread-safe. Puede crear múltiples instancias en entornos concurrentes.
  4. No existe modularidad en las rutinas de alimentación:

    • Todo está embebido en el método Alimentar. No hay construcción paso a paso.
  5. No se aprovechan patrones para reutilización:

    • Rutinas exitosas no se clonan ni reutilizan (Prototype ausente).

1. Factory Method

  • Se elimina la lógica rígida de if/else.
  • Cada animal tendrá su propia clase Dieta y una fábrica asociada.
// Producto
public abstract class Dieta
{
    public abstract void Preparar();
}

// Productos Concretos
public class DietaVaca : Dieta
{
    public override void Preparar()
    {
        Console.WriteLine("Vaca: heno, agua, sal mineral.");
    }
}

public class DietaCerdo : Dieta
{
    public override void Preparar()
    {
        Console.WriteLine("Cerdo: granos, jugo.");
    }
}

public class DietaGallina : Dieta
{
    public override void Preparar()
    {
        Console.WriteLine("Gallina: semillas, agua.");
    }
}

// Creador (Factory Method)
public abstract class DietaFactory
{
    public abstract Dieta CrearDieta();
}

// Fabricas concretas
public class VacaFactory : DietaFactory
{
    public override Dieta CrearDieta() => new DietaVaca();
}

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

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

2. Abstract Factory

Permite crear familias de productos (Alimento, Bebida, Suplemento).

Evita inconsistencias al combinar tipos de comida.

// Abstract Factory
public interface IAlimentacionFactory
{
    string CrearAlimento();
    string CrearBebida();
    string CrearSuplemento();
}

// Fábricas concretas
public class AlimentacionVacaFactory : IAlimentacionFactory
{
    public string CrearAlimento() => "Heno";
    public string CrearBebida() => "Agua";
    public string CrearSuplemento() => "Bloque de sal";
}

public class AlimentacionCerdoFactory : IAlimentacionFactory
{
    public string CrearAlimento() => "Granos";
    public string CrearBebida() => "Jugo";
    public string CrearSuplemento() => "Vitaminas";
}

public class AlimentacionGallinaFactory : IAlimentacionFactory
{
    public string CrearAlimento() => "Semillas";
    public string CrearBebida() => "Agua";
    public string CrearSuplemento() => "Calcio";
}

3. Builder

Construye rutinas completas paso a paso (desayuno, snack, cena).

// Producto complejo
public class RutinaAlimentacion
{
    private List<string> pasos = new List<string>();
    public void AgregarPaso(string paso) => pasos.Add(paso);
    public void MostrarRutina()
    {
        Console.WriteLine("Rutina de Alimentación:");
        pasos.ForEach(p => Console.WriteLine($" - {p}"));
    }
}

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

// Builder concreto
public class RutinaVacaBuilder : IRutinaBuilder
{
    private RutinaAlimentacion rutina = new RutinaAlimentacion();
    public void PrepararDesayuno() => rutina.AgregarPaso("Heno y agua fresca");
    public void PrepararSnack() => rutina.AgregarPaso("Sal mineral");
    public void PrepararCena() => rutina.AgregarPaso("Heno seco y agua");
    public RutinaAlimentacion ObtenerRutina() => rutina;
}

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

4. Prototype

Clona rutinas exitosas para reusarlas en nuevos animales.

public class RutinaPrototype : ICloneable
{
    public string Nombre { get; set; }
    public List<string> Pasos { get; set; } = new List<string>();

    public object Clone()
    {
        // Clonación profunda
        return new RutinaPrototype
        {
            Nombre = this.Nombre,
            Pasos = new List<string>(this.Pasos)
        };
    }

    public void Mostrar()
    {
        Console.WriteLine($"Rutina: {Nombre}");
        Pasos.ForEach(p => Console.WriteLine($" - {p}"));
    }
}

5. Singleton Mejorado

Thread-safe con Lazy.

public class RegistroGlobalAlimentacion
{
    private static readonly Lazy<RegistroGlobalAlimentacion> instancia =
        new Lazy<RegistroGlobalAlimentacion>(() => new RegistroGlobalAlimentacion());

    private RegistroGlobalAlimentacion() {}

    public static RegistroGlobalAlimentacion Instancia => instancia.Value;

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

Ejemplo de uso en Program.cs

   using System;

namespace GranjaInteligente
{
    class Program
    {
        static void Main(string[] args)
        {
            // Factory Method
            DietaFactory vacaFactory = new VacaFactory();
            Dieta dietaVaca = vacaFactory.CrearDieta();
            dietaVaca.Preparar();

            // Abstract Factory
            IAlimentacionFactory alimentacionVaca = new AlimentacionVacaFactory();
            Console.WriteLine($"Vaca recibe: {alimentacionVaca.CrearAlimento()}, {alimentacionVaca.CrearBebida()}, {alimentacionVaca.CrearSuplemento()}");

            // Builder
            var director = new RutinaDirector();
            var rutinaBuilder = new RutinaVacaBuilder();
            var rutina = director.ConstruirRutina(rutinaBuilder);
            rutina.MostrarRutina();

            // Prototype
            var rutinaBase = new RutinaPrototype { Nombre = "Rutina Original" };
            rutinaBase.Pasos.Add("Desayuno con heno");
            rutinaBase.Pasos.Add("Snack con sal mineral");

            var rutinaClonada = (RutinaPrototype)rutinaBase.Clone();
            rutinaClonada.Nombre = "Rutina Clonada";
            rutinaClonada.Mostrar();

            // Singleton
            var registro = RegistroGlobalAlimentacion.Instancia;
            registro.Registrar("Ciclo de alimentación completado.");
        }
    }
}
@IoTeacher
Copy link

Aquí tienes una retroalimentación breve para Joel con su calificación

Retroalimentación

Joel, tu solución muestra un uso apropiado de Abstract Factory para producir mascotas y servicios coherentes, Singleton para el hotel de mascotas, y Builder para construir facturas o paquetes de servicios paso a paso. El Main integra esas piezas en un flujo lógico: creación de mascota, asignación de servicios, facturación, etc. Como mejora, podrías:

  • Incluir el patrón Prototype para clonar mascotas o paquetes de servicios, especialmente para reutilización.
  • Garantizar clonación profunda si los objetos internos tienen estructuras mutables.
  • Facilitar la extensión a nuevos tipos de mascota o servicios sin tener que modificar muchas clases centrales.
  • Añadir validaciones de error y pruebas unitarias para cubrir escenarios límite.

Calificación sugerida: 89 / 100

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