mercredi 27 juin 2018

Template Method and Remove If Statements

So, Im studying Design Patterns, and Im studying the Template Method.

From how I understood it, It is a set of Methods (The skeleton) wrapped in a Method (Operation) on an Abstract Class (If done via heritage), where different Concrete Subclasses write their own implementation of those methods (Not all of them).

But I have a doubt, what happens if some, maybe 2 methods of the skeleton are not used by a certain concretion?, Here I have an example I made, which totally violates the SRP:

using System;

namespace TemplatePattern
{
    public abstract class Coffee
    {

        public void MakeCoffee()
        {
            HeatWater();

            PutCoffee();

            if (HaveMilk())
            {
                PutMilk();
            }

            if (HaveGratedChocolate())
            {
                PutGratedChocolate();
            }

            PutSweetener();

            ServeCoffee();
        }

        internal void HeatWater()
        {
            Console.WriteLine($"I heated the water");
        }

        internal void ServeCoffee()
        {
            Console.WriteLine($"Coffee Served");
        }

        internal void PutCoffee()
        {
            Console.WriteLine("I put 2 spoons of Coffee");
        }

        internal virtual void PutMilk() { }

        internal virtual void PutGratedChocolate() { }

        internal abstract void PutSweetener();

        public virtual bool HaveMilk()
        {
            return false;
        }

        public virtual bool HaveGratedChocolate()
        {
            return false;
        }
    }
}

Concrete class SimpleCoffeeWithMilk:

using System;
namespace TemplatePattern
{
    public class SimpleCoffeWithMilk : Coffee
    {

        public override bool HaveMilk()
        {
            return true;
        }

        internal override void PutSweetener()
        {
            Console.WriteLine($"I put 1 spoon of Sugar");
        }

        internal override void PutMilk()
        {
            Console.WriteLine($"I put 100Cc of Milk");
        }
    }
}

Another Concrete class:

using System;

namespace TemplatePattern
{
    public class CoffeeWithChocolate : Coffee
    {
        public override bool HaveGratedChocolate()
        {
            return true;
        }

        internal override void PutGratedChocolate()
        {
            Console.WriteLine("Le puse choco rayado");
        }

        internal override void PutSweetener()
        {
            Console.WriteLine($"Le puse azucar");
        }

    }
}

Main Entry Point:

using System;

namespace TemplatePattern
{
    class Program
    {
        static void Main(string[] args)
        {
            SimpleCoffeWithMilk coffeWithMilk = new SimpleCoffeWithMilk();
            CoffeeWithChocolate coffeeWithChocolate = new CoffeeWithChocolate();

            coffeWithMilk.MakeCoffee();

            Console.WriteLine("\n\n");

            coffeeWithChocolate.MakeCoffee();

            Console.ReadLine();

        }
    }
}

The idea is to get rid of those If's Statements, is there any way of doing this with the template method, where some of the methods execute depending of the concrete class?

I was thinking in creating interfaces like ICoffeeWithMilk with PutMilk() method on it and implement that interface on my SimpleCoffeeWithMilk concrete class, but watching the UMLs, the Template Method for what I saw does not rely on Interfaces.

Aucun commentaire:

Enregistrer un commentaire