Let's say I want to make a pie baking application. It should be able to create an apple pie as well as a strawberry pie. But I would like to have the option to add more different pie types later on. So I make an interface called IPie
, like this:
interface IPie
{
List<string> Ingredients { get; set; }
IPieMaker Maker { get; set; }
}
interface IPieMaker
{
Task MakePie();
}
I could then have an implementation of IPieMaker
for each type of pie. E.g. for apple pie, like this:
public AppliePieMaker : IPieMake
{
public Task MakePie()
{
// ...do something with ingredients, specific to the apple pie
}
}
The actual implementation is built into the specific pie. For instance, apple pie could look like this:
public class ApplePie : IPie
{
List<string> Ingredients { get; set; } = new List<string> { "Apples", "Flour", "Eggs" };
IPieMaker Maker { get; set; } = new ApplePieMaker();
}
So no matter the type of the pie, I'm always sure it can be made. Like this:
var pies = new List<IPie>
{
new ApplePie(),
new StrawBerryPie(),
};
foreach (var pie in pies)
{
pie.Maker.MakePie();
}
Now here comes the actual question:
All of the above depends on the on the maker being a property on the pie class (the implementation of IPie
). What if I would like a more functional apporach, where the PieMaker
is outside the class? So that I call it like this:
// From here, the pies are simple dumb data structures
var pies = new List<IPie>
{
new ApplePie(),
new StrawBerryPie(),
};
foreach (var pie in pies)
{
var maker = new PieMaker(pie);
maker.MakePie();
}
How do I make the PieMaker
class handle the different types of pie? Obviously it could start with a giant switch statement and then route the calls to specific pie makers (ApplePieMaker, StrawberryPieMaker, etc.), but isn't that a bad practice? How would you do this in functional programming?
(I am aware that I am not doing actual functional programming, but I like the simplicity of it, which is why I am curious about a less object oriented approach).