So far even though we looked at the different variations of the factory design pattern we really only
covered the one Gangle for design pattern and that is the factory method so it's time for us to cover
the other side which is the abstract factory and just as the name suggests is this idea of families
or factories or families or products and corresponding families of factories which use inheritance to
actually allow you to polymorphically call on the different factory.
So this is going to be a bit of a convoluted example but we're going to go through it anyway and see
how it goes so we're going to try to emulate a simple kind of hot drink machine that can make tea or
coffee or something else.
I'm going to go and make a let's make a header only implementation on this one so I'll make a C++ header.
We'll call it hot drink for example So here let me get rid of all this junk.
We're going to make an interface first of all we'll make an interface called the hot drink.
So struct hot drink and what I'm going to do is I'll make a virtual destructor virtual drink default
and I will also have some sort of method for let's say preparing that drink salt have virtual void prepare
where you prepare the drink with specified volume and that's going to be virtual.
So now we're going to have a family of different products so you might have a hot drinks or just tea
or coffee for example.
So in the case of tea We're going to inherit from hard drink.
And what I'm going to do is I will implement.
Let's actually use the cogeneration mechanism so in the prepare function I will simply see out of the
fact that we take a tea bag and yes we do need stream and lots of other things besides So it's included
ice cream and will import all.
Using namespace SDD here just for brevity.
So.
So we take the tea bag.
We boil water.
We pour however many milliliters are acquired milliliters and that's pretty much it.
So we are pretty much good to go.
Basically you can you can add some lemon here.
Let me just do a line break and add some lemon and that's pretty much it.
So that's how you make tea.
And in a similar fashion we're going to have yet another product I'm going to have coffee which is also
a hot drink.
So once again I will generate the appropriate implementation and here will do something different.
Will say grind some beans boil water poor however many leaders we actually require your line formatting
and go milliliters and enjoy.
Maybe add some cream if you want to.
So this is the implementation of the coffee ordering so we have a family of objects and what we can
now do is that we can have a corresponding family of factories.
In actual fact so we're going to have we have a hot drink so we're going to have a hot drink factory.
So let's go and actually generates.
Let's just make a header file once again.
I'm going to call it hot drink factory and I'll define the interface.
So the interface for a Hodding factory is going to be something like the following.
And we do need the hot drink obviously our drinks or HP in other for this whole thing to work.
So we're going to have a structure called hot drink factory and here I'll have a pure virtual method.
Once again let's use SharePoint as shall we say I'll have a unique PVR which is going to do a hot drink.
So we're going to return a hot drink.
All I'm going to need another include somewhere maybe I maybe I can stick it into Codrington HPB let's
just stick it in here for simplicity so let's get a memory in here and this way we're going to propagate
through it here.
So we're going to have a factory method called the make which is going to be pure virtual So whatever
hot drink factory implements this Woodring factory has to have an interface member called make.
So now we can make the actual factory so we can make the factory and a let's say a coffee factory.
So for example if I wanted to factory this is going to be hard drink factory like so and I will go and
implement the members here and I will return simply make the make unique rather I will make some tea.
That's all that I would need to do and the same goes for the coffee factory obviously.
So we're going to have struck the coffee factory I can actually duplicate what I've done here already
because it's almost the same implementation at least for our purposes in the real world you would have
obviously significant differences between the two.
But here we're just going to have a coffee factory and here.
Instead of making tea We're going to make coffee.
OK so what do we have now we have a family of products.
So a family of drinks in this case we have tea and coffee and we have their corresponding factories
so essentially we have this idea of an abstract factory right here so this is the abstract factory called
Hodding factory from which we actually inherit and then we can actually try and make certain products.
So let's go into Maine and we're going to include all that stuff that we made so I'm going to include
the Hodding factory like so.
And then what we're going to do is we're going to just define some sort of method which is going to
make a drink depending on the name of the drink.
So for example I will have a unique PDR since all of our factories use smart pointers unique TTR of
hard drink.
So it's going to be make drink.
And you simply specify the type which is going to be a string.
There we go.
OK so the idea here is that depending on whether you want tea or coffee you would typically go ahead
and just do and if so let's first of all initialising unique with your hot drink and let's call it this
drink.
And then you would have in a typical case if you weren't using abstract factory you would have an if
statement.
So if you didn't have an abstract factor you would say something like if type is equal to T then you
would assign the drawing.
So you would make unique t.
You would have the T.
So prepare well let's say 200 millimeters.
And that would be the result.
Otherwise you would do something different.
So let's see what's going on here.
So applying opera.
No this is actually correct.
This is what the Ivey's bugs I these have plenty of issues I'm afraid.
So the alternative is you're making coffee so you would have a drink equals make unique coffee and then
you would say drink prepare with a different volume let's say 50 milliliters and you would return that
drink whatever that happens to be.
So return a drink like so.
And that's pretty much it.
This is how you would make tea or coffee.
So here you would say all the equals make drink tea for example.
This is how you would make some tea.
So this would actually work but we have our abstract factory instead which kind of takes care of some
of these issues at the very least So what we can do is we can make a drink factory.
OK so what is a drink factory and how does it work.
Well the dream factory is something that's actually going to kind of keep track of the kind of stuff
that we have the kind of factories that we have generally.
So let's actually make it if we go and make Well it should be a header file rather than in the source
file.
All code Kudrin factory.
So a drink factory is a concrete implementation of the abstract factory or in other words it's a facilitator
for actually using all of the different factories that we made and having them in some sort of map and
exposing them to whoever is actually interested in making a drink.
So we're going to include lots of things here.
I will include during HBP and I will also include a hot drink factory HIPPA and we might need other
includes later on like for example I think I'm going to need a map at some point.
And I get all of this important so we're going to have a class.
Let's have a class called drink factory.
So this class is actually going to help us construct drinks on the basis of the different factories
now different ways as to how you want to actually play this because for example what in our case what
I'm going to do is I'm going to make a map so I'm going to make a map from the names of the drinks to
the factories which actually are capable of producing those drinks.
I'm going to have a map from a string to a unique PDR of hard drink factory and I'm going to call them
hot factories because who knows you might have cold drinks as well.
So this is going to be a private thing and then we're going to have a couple of public members.
So when we initialize the drink factory I don't want to actually go on to select none.
I guess I went to an empty constructor here.
So when you initialize it what you can do is you can add all those factories into the map and unfortunately
in C++ we don't have reflection so we have to do this by hand so I would say hold factories with the
name coffee is equal to make unique and you would construct the coffee factory and in a similar fashion.
Let me actually just duplicate this you would have a factory called T T and you would make unique a
tea factory.
So now we're using this polymorphism of the factories to kind of keep all the factories in a single
collection.
When somebody wants a drink we can provide an interface for that so you can have a unique VTR returning
a hot drink.
So unique with your drink we're going to call it may drink and it's going to take the name of the doing
that we want to make and here all we have to do is we have to make a loop hop into our map and actually
make that drink auto drink equals its factories to look up with name and then call the make call them
make function on it.
That's pretty much all that we would generally have to do.
And then we would prepare the drink or drink prepare with a certain amount at the moment I'm just going
to use a fixed amount.
We can we can sort of tweak it later on then we can return the drink.
That's pretty much it.
So the upside is that instead of actually calling this kind of implementation with an if statement then
whatever you make it more organized.
So essentially what you do is you make a drink factory.
So we we actually use one of these drink factories.
It's called The F.
And then you say DFA don't make drink and we make let's say a coffee.
And of course yes we do need to include the appropriate header here.
I can say auto C equals coffee and that's it.
My coffee is done we can actually run this we can execute this and see what we actually get.
All right so as you can see we grind some beans we're both somewhat are we poor our milliliters we add
cream and we enjoy the coffee.
So this is the idea of an abstract factory.
Let me just reiterate this again so you have a family of products in this case you have a family of
different hot drinks and you have a corresponding family of factories where is it or drink factory.
There we go.
So you have corresponding families of factories and what you can do now is because they all share a
common interface.
In this case they all share the make member function.
What you can do is you can stick them into any kind of data structure.
So in this case I need a drink factory or where I stuck them into a map from string to whatever their
implementation actually is and when you invoke one of them then you simply get the appropriate element
by key from the map and then you call me on it.
Polymorphically and you you get the drink you prepare the drink.
The drink itself also is polymorphic as you may have guessed because it's a family of factories and
the family of products so you call something polymorphically on the drink and you return a drink.
In this case as a unique point here and this is pretty much the gist of the abstract factory design
pattern.