mercredi 18 juillet 2018

Obtaining a total for different subclasses using Observer

Im studying design patterns and I got the idea of mixing Template Pattern with Observer. The idea of the observer is to quantify and accumulate a property of subclasses that inherits from the Abstract class and then notify it.

The idea is to just implement both design patterns and I had some doubts while doing it.

1) One of my properties for CoffeeWithMilk is the same as CoffeeWithChocolateAndMilk (AmountOfMilk). Do I have to repeat this logic for every concrete class or is there any other way to avoid DRY?.

2) I have to cast both of these two classes as IMilkSpent, is there any other way to change this?

3) Right now the MilkManager is the one notifying the total amount of milk spent, is there any other way?.

public class NoMilkException : Exception
    {
        public NoMilkException(){}

        public NoMilkException(int amount) : base(String.Format("The amount of milk must be more than 0 Cc, you chosed {0} Cc",amount)){}
    }

public interface IMilkSpent
{
    int InformMilkUsage();
}

public interface Subject 
{
    void Attach(IMilkSpent observer);
    void Dettach(IMilkSpent observer);
    void NotifyMilkUsageTotal();
}

public class MilkManager : Subject
    {
        public int MilkSpentTotal { get; set; }

        private List<IMilkSpent> Observers = new List<IMilkSpent>();

        public void Attach(IMilkSpent observer)
        {
            Observers.Add(observer);
        }

        public void Dettach(IMilkSpent observer)
        {
            Observers.Remove(observer);
        }

        public void NotifyMilkUsageTotal()
        {
            MilkSpentTotal = 0;
            foreach(IMilkSpent observer in Observers)
            {
                MilkSpentTotal += observer.InformMilkUsage();
            }

            Console.WriteLine("Amount of Milk spent was: {0} ", MilkSpentTotal);
        }
    }

 public abstract class AbstractCoffee
    {
        public void MakeCoffee()
        {
            PrepareCup(); 
            BoilWater(); 
            PutCoffee(); 
            AddIngredientsBeforeServing(); 
            ServeCoffee();  
        }

        internal virtual void AddIngredientsBeforeServing(){}

        protected void PutCoffee()
        {
            Console.WriteLine(@"I added Coffee");
        }

        protected void PrepareCup()
        {
            Console.WriteLine(@"I warmed up the cup");
        }

        protected void BoilWater()
        {
            Console.WriteLine(@"The water is boiled");
        }

        protected void ServeCoffee()
        {
            Console.WriteLine(@"Here is your cup of coffee");
            Console.WriteLine("\n");
        }
    }

public class CoffeeWithMilk : AbstractCoffee, IMilkSpent
    {
        private int _amountOfMilk = 0;

        public int AmountOfMilk
        {
            get
            {
                return _amountOfMilk;
            }
            set
            {
                if(value <= 0)
                {
                    throw new NoMilkException(_amountOfMilk);
                }
                else
                {
                    _amountOfMilk = value;
                }
                //value <= 0 ? _amountOfMilk = value : throw new NoMilkException(_amountOfMIlk);
            }
        }

        public CoffeeWithMilk(int amountOfMilk)
        {
            this.AmountOfMilk = amountOfMilk;
        }

        internal override void AddIngredientsBeforeServing()
        {
            PutMilk();
            PutSweet();
        }

        public int InformMilkUsage()
        {
            return AmountOfMilk;
        }

        protected void PutMilk()
        {
            Console.WriteLine("I put {0} Cc in the cup of coffee",_amountOfMilk);
        }

        protected void PutSweet()
        {
            Console.WriteLine(@"I put Sugar on your coffee");
        }
    }

public class CoffeeWithChocolate : AbstractCoffee
    {
        internal override void AddIngredientsBeforeServing()
        {
            PutChocolate();
            PutSweet();
        }

        protected void PutChocolate()
        {
            Console.WriteLine(@"I put Chocolate on your coffee");
        }

        protected void PutSweet()
        {
            Console.WriteLine(@"I put Sugar on your coffee");
        }
    }

public class CoffeeWithChocolateAndMilk : AbstractCoffee, IMilkSpent
    {
        private int _amountOfMilk = 0;

        public int AmountOfMilk
        {
            get
            {
                return _amountOfMilk;
            }
            set
            {
                if(value <= 0)
                {
                    throw new NoMilkException(_amountOfMilk);
                }
                else
                {
                    _amountOfMilk = value;
                }
                //value <= 0 ? _amountOfMilk = value : throw new NoMilkException(_amountOfMIlk);
            }
        }

        public int InformMilkUsage()
        {
            return AmountOfMilk;
        }

        public CoffeeWithChocolateAndMilk(int amountOfMilk)
        {
            this.AmountOfMilk = amountOfMilk;
        }

        internal override void AddIngredientsBeforeServing()
        {
            PutMilk();
            PutChocolate();
            PutSweet();
        }

        protected void PutMilk()
        {
            Console.WriteLine("I put {0} Cc in the cup of coffee",_amountOfMilk);
        }

        protected void PutChocolate()
        {
            Console.WriteLine(@"I put Chocolate on your coffee");
        }

        protected void PutSweet()
        {
            Console.WriteLine(@"I put Sweetener on your coffee");
        }
    }

public class Program
    {
        public static void Main(string[] args)
        {
            List<AbstractCoffee> coffeesPrepared = new List<AbstractCoffee>();
            MilkManager manager = new MilkManager();

            AbstractCoffee coffeWithMilk = new CoffeeWithMilk(1);
            AbstractCoffee coffeeWithChocolate = new CoffeeWithChocolate();
            AbstractCoffee coffeeWithChocolateAndMilk = new CoffeeWithChocolateAndMilk(1);

            coffeesPrepared.Add(coffeWithMilk);
            coffeesPrepared.Add(coffeeWithChocolate);
            coffeesPrepared.Add(coffeeWithChocolateAndMilk);

            manager.Attach((IMilkSpent)coffeWithMilk);
            manager.Attach((IMilkSpent)coffeeWithChocolateAndMilk);

            coffeesPrepared.ForEach(c => c.MakeCoffee());

            manager.NotifyMilkUsageTotal();
            manager.NotifyMilkUsageTotal();
        }
    }

Aucun commentaire:

Enregistrer un commentaire