We were discussing at work a scenario where you would want to be able to execute behaviours from a controlling block of code and pass in many types of common behaviours. My mind went straight to abstract and base classes to solve it. However someone said it can be done using composition over inheritence. It is not something I had considered before and was interested to find out more and see if i could implement something similar in C#.
So given that i am partial to a hot beverage i decided to use the steps to prepare different types of these as they have shared steps or behaviours. i.e. boiling hot water, adding sugar, milk and pouring hot water into the cup. I started with the idea of an interface to represent the step.
public interface IStep
{
void Do();
}
I then create a class with one method on it to call the Do method on a step. The CuppaFather method being inspired by Mrs Doyle from Father Ted. The class constructor take an instance of IStep and the CuppaFather method calls the Do method on it.
public class BrewUp
{
private readonly IStep _step;
public BrewUp(IStep step)
{
_step = step;
}
public void CuppaFather()
{
_step.Do();
}
}
I can then implement IStep for as many steps as i can think of for making say a cup of coffee. So fill the kettle, boil it, add coffee to the mug, pour the hot water in and add milk. (Or milk first, i am not getting into THAT debate though) So here is the code to fill the kettle for instance. Note how it also has a constructor taking an IStep instance. When its Do method is called we check to see if we got an IStep instance and if so we call it’s Do method, thereby chaining the steps/behaviours together.
public class FillKettle : IStep
{
private readonly IStep _step;
public FillKettle(IStep step)
{
_step = step;
}
public void Do()
{
Console.WriteLine("Filling the Kettle");
if (_step == null)
return;
_step.Do();
}
}
This is then pull together into a console app by passing in new instances of each step to the previous one.
class Program
{
static void Main(string[] args)
{
var brewUp = new BrewUp(new FillKettle(new BoilKettle(new AddCoffeeToCup(new AddMilk(null)))));
brewUp.CuppaFather();
Console.ReadKey();
}
}
This gives us an output of the steps to make a basic cup of coffee…not very exiciting so far.
What we really want is to be able to input the hot beverage we want steps for and get those steps back reusing the common steps, maybe even add in some “extras” like chocolate sprinkles or sugar (and the number of spoons).
That is for another time…
Part 2 now published Decorator or Russian Dolls Part 2