The Factory Pattern in Python // Separate creation from use

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
the factory is a design pattern that i use really often when i write software today i'm going to show you an example of how it works and how you can use it to separate creation from use which is really powerful before we dive in i have something for you i wrote down the seven main things that i think about when designing a new feature or new software application you can get it for free at ironcodes.com design guide it's pretty short so pdf contains a couple of bullet points some notes from me here and there i think you'll find it really useful so get it at rmcode.com design guide now let's dive into the factory pattern what we have here is a video and audio exporting example as you can see i did a little bit of preparation work i created a video exporter abstract class that's a basic representation of a video exporting codec and that has two methods prepare export and do the export prepare export gets the actual video data and do export gets a folder i'm using the barflip.path type here to represent paths and that exports the video data to folder at least that's the idea and then we have several specific implementations for this class there is lossless video exporter that export data in lossless format there's also an h.264 video exporting codec with baseline profile so that's basically an economic mode lower quality and finally there is a higher quality h.264 export format with four to two chroma sampling and 10 bit colors and stuff like that it doesn't really matter for this example but it's a higher quality one and a similar thing i did for the audio exporter we have an audio exporter abstract class that has prepare export and duty export but that gets audio data but do export also gets a folder so it looks a bit similar and then there is an aac audio exporting codec and we have a wave audio exporter which is lossless so again also here we have kind of a lower economic quality and a high quality that you would use for masters then there is a main function that first reads the export quality that the user wants so we ask the user whether they want low high or master and then depending on that value that you got we're going to create these specific exporters so we start with these variables video and audio exporter if the quality is low we're creating the base profile h.264 video exporter and the aac audio exporter if the quality is high we're using the high quality profile for video and also aac if it's master quality then we're going for lossless video and lossless audio in the form of a wav file so the choice of the kind of exports that we want to use is here then we call the function we prepare the export and we do the actual export to a particular folder so let's run this code and see what happens so now i can enter a desired output quality like if i choose low then it's going to export with the h64 baseline export and ac export and if i run this again and i choose for example master quality then i'm getting the video and audio export in master quality now if you look at this code you see that there's in particular problem with the main function in that it has way too many responsibilities it's responsible for asking the user which quality they want it's responsible for then mapping that desired quality to actual objects and then it does the actual export which is a lot of different things so main has weak or low cohesion at the moment it does a lot of different things it also has a lot of coupling because main is creating all these specific instances of video and audio exporters so that means maine needs to know about the existence of all these different classes and in this example we maybe have two or three audio video exporters but if you have any serious video or the audio editing program you're going to have many different export formats and that's going to lead to lots and lots of different classes and that's going to lead to lots and lots of complicated if else statements another thing is that because the way this is set up is that we don't really have the option to create our own custom export format so now we have low high and master but maybe we want a high audio quality low video quality option or we want something else and that's also really hard to add at the moment the factory pattern is a classic from the gang of four design patterns book the goal of the pattern is to help write code that separates creation from use in other words you should create your objects in a different place than where you use them this is very helpful because then the code that you write doesn't have to know anything about how the objects are created when you use them and that means that if in a later stage you decide to change out those objects by other objects you don't have to change the original code what the factory does is that it takes care of the creation for you so that you can use those objects without knowing the specifics and the way that it works is that we need to create an in this case an exporter factory that gives us the objects that we need so let's start there and let's create an exporter factory that can give us a video exporter and an audio exporter so that's an abstract base class the factory is going to have two methods one method that gives us a video exporter and one method that gives us an audio exporter you see it's useful that we already had these abstract classes for video and audio exporters that makes the job a lot easier so get video exporter get audio exporter and each of these returns a new instance so it's also helpful to write down in the documentation that the factory is actually not the owner of these things you can do with them basically whatever you want the factory doesn't keep a reference to this instances so let's write that down as well for python it doesn't really matter that much because python has a reference counting so if you don't use an object anymore it's going to be garbage collected automatically but sometimes it's useful to know that you don't have to tell the factory anything once you're done with the object the object is yours it's your responsibility so this is our exporter factory that's going to provide us with the instances that we need and now we can create concrete factories that are subclasses of this abstract exporter factory and these concrete factories are going to give us the objects that we need so for example we could create a low quality exporter factory or put a bit more positively a fast exporter and that's a subclass of exporter factory and it's going to implement these methods here copy that over let's also add a log string in this case the video export is going to be an h.264 baseline video exporter because that's the faster one and the audio exporter is an aac exporter so this is our fast exporter and we can also create a high quality exporter and that's going to give us an h.264 high quality video exporter and an ac audio exporter as well and then let's also create a master quality exporter which is for the really high quality stuff and that's the slowest obviously so the video exporter is lossless and audio exporter is lossless audio now we've created our three factories for low high and master level quality now let's rework the main function to increase the cohesion and separate out a bit and use this factory pattern so the first thing we're going to do is take this piece of code that's reading the desired export quality from the user input and create a separate function that provides us with a specific factory that the user wants so what i'm going to do is i'm going to remove this here and i'm going to define another function called read exporter which is going to give us an exporter factory this stuff i'm going to put here so now instead of having a string value we're going to need to construct an exporter factory and here's a nice trick that you can do let's create a factories object and that's a dictionary containing a factory for each of the quality types that want to have so low quality is a fast exporter high quality is a high quality exporter and the master quality is a master quality exporter so we have our three factories now and what we can do we don't need this variable here anymore is that we're going into the while loop reading the export quality and here if the export quality is in one of these three things then we're going to return the factory belonging to it there we go and actually now this we can replace with the dictionary so now there's only one place where we're defining the factories that are available so this gives us the exporter factory then in the main function we're going to create the factory and now that we have the factory we can retrieve the video and audio exporters using the get video exporter and get audio exporter methods from the factory so now we have our video or the exporters and actually this stuff we don't need anymore so let's save this and let's run the code so we enter the desired quality hi and then it's going to prepare the video and audio data in the format that we like to have and let's also do master quality now you see it's preparing and exporting the data in a lossless format if you look at the main function now you see that it's no longer responsible for as many things it's the only thing it needs to do is retrieve the video and the audio exporter from the factory and then actually do the export and that's it and reading the export is the function that's responsible for creating the factory that we want to use for completeness let's add a dock string there we go so we've been able to split the responsibility of reading the exporter and then actually using the exporter separating creation from use so these functions now have much higher cohesion than in the first version and the interesting thing is that there is also less coupling because main no longer has to know anything about specific exporter codecs because that's all handled somewhere else even read export doesn't need to know that it only needs to know about the factories that exist there's one more thing we can do to improve this still a bit which is that at the moment main is still responsible for reading the factory here using read exporter and maybe we want to use the function in another setting where we're not reading the export from the input but simply providing it so what you can do to spice this up a bit is that we actually provide the factory to the main function as an argument so main gets a exporter factory this i'm going to remove here and we're going to put in here there we go so now it does exactly the same except that may now gets the factory as an argument and we have more flexibility into how we're going to provide that factory to the main function this is a good example of using dependency injection it's something i talked about before because we're injecting the dependency on the factory into the main function and even better we're even using dependency inversion here because the factory itself here export a factory as you can see it's an abstract class so main gets an abstract class but we're creating a concrete factory subclass that main doesn't need to know anything about it only needs to know about the exporter factory overall factories work really well if you want to separate creation from use and one of the strong points of factories is that they allow you to group objects that belong together in this example we have a low quality exporter setup and a high quality exporter setup so factories are really useful if you want to do something like this another example of this is a web shop where you have settings per country like currency language tax rates shipping rates and those kind of things factories work less well if you want to allow any combination of things for example if you want to let the user define presets for which combinations of codecs that the user wants because in that case you need to create a factory class for every possible combination if this is what you need and it's better to use a combination of composition and dependency inversion because that overall gives you a little bit more flexibility while still allowing for the lower coupling but of course then you won't have the advantage of being able to define specific factories beforehand there's a recent video that i did about dependency inversion that you could take a look at if you want to know how to do that so hope you like this example let me know in the comments if the factory pattern is something that you plan to use in your code subscribe to my channel if you haven't done so already thanks for watching take care and see you in the next video
Info
Channel: ArjanCodes
Views: 53,094
Rating: undefined out of 5
Keywords: factory pattern in python, factory pattern, factory design pattern, design pattern factory, abstract factory, abstract factory design pattern vs factory pattern, abstract factory design pattern, abstract factory pattern, software design patterns python, software design patterns gang of four, software design patterns course, software design patterns factory, design patterns, python design patterns, design pattern, design patterns in python, Factory pattern example
Id: s_4ZrtQs8Do
Channel Id: undefined
Length: 14min 57sec (897 seconds)
Published: Fri Jul 16 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.