hey my name is Forest welcome back in today's video you're going to learn about seven different software design patterns many of which you already use whether you realize it or not because simply put there solutions to Common programming problems that appear over and over and over and over regardless of what language or platform you're using it's not complicated it's just a matter of knowing them so you can understand when to use them and to actually use them because they are common practice for a reason because they're good back in 1994 these four developers known as
the gang of four wrote this book they documented cataloged and formalized 23 commonly used design patterns so i' highly recommend reading that book reading all the way through it because all of those are heavily applicable today we're not going to go over all 23 but I must note that all 23 do fall into three buckets creational patterns are all about object creation so instead of creating objects directly these patterns give you more flexibility on how objects come into existence structural patterns it's a second in category deal with how objects relate to each other think of
them as blueprints for building something building larger structures from Individual pieces like Legos so creational patterns object creation structural patterns the structure of how they relate to each other in the third category behavioral patterns which handle communication between objects how they interact and distribute responsibilities which includes the greatest pattern of all time the strategy pattern just just always use a strategy pattern if you take anything nothing from this video take that but let's dive deeper into these three creational patterns starting with the Singleton pattern everyone hates it until they need it think of the Singleton
pattern as your apps logging system when errors happen across your app which we all know will happen since you're the one coding it you want one Central logger handling everything using consistent formatting and and writing to the same file or service you don't want you don't want different loggers in interfering with each other for example this is where you have multiple loggers and creating chaos logger one new logger logger two new logger which is another logger writing to the same file the single T pattern you have a single logger that everyone uses and you get
the instance from said logger logger one logger two one logger get instance of that logger stored in logger you'll want to use the Singleton pattern when you absolutely need a single instance that's accessible globally like a database connection pool or the logger but it does have some trade-offs the good is that you get guaranteed single instance and Global access the bad is that well it's a bit of a nightmare to test and that's because you can't easily mock it you can mock it but you can't easily mock it and if you want to call that
a skill issue by all means try it yourself then get back to me and tell me how it went but also in multi-threaded environments you need special handling to prevent creating multiple instances but if you want me to really scare you I'm going to I'm going to use this analogy a Singleton is basically just a global a glorified Global variable yeah think about that for a second makes me nervous just thinking about it but I'm not trying to scare you it's not all bad or anything like that it's like a using a hammer to solve
your problems sure it works great on nails but not everything is a nail that's that's the thing just use it when you genuinely need single instance guarantee not when you just want a global state next up is the Builder pattern never tried to create something that has like 15 different optional parameters just me no all right anyway you can think of the Builder pattern as uh well think about creating a complex API request you've got headers query prams body data data data timeout settings rry logic trying to do all of that in a single Construction
will look something like this as you can see new HTTP requests and we're just throwing in API example.com post and all of this based on our HTTP request class like this however the beauty of the Builder pattern is that you can chain methods in any order you can skip the optional ones and your code actually reads like English check this out so here's our class request Builder which starts off similar to our HTTP request URL string method string headers record string string however here we're assigning it an initial value in the below we have all
of our methods as you can see and our Constructor results in a beautiful Builder P pattern as such and what's great about this is that if you want to add any new options later you just have to add a method to the class no need to go through and update every single place you're creating an object you want to use a builder pattern every time you're staring at a Constructor that has more parameters than you have fingers or when you need to construct object step by step like cooking you don't just throw all the ingredients
in at once you follow a recipe step by step the downside is you end up writing more code up front that is but trust me your future self and all of your teammates will than you when they can actually understand what in the world's going on and can create objects without you know playing the game oh I wonder what this parameter does next is the factory pattern you know how an object-oriented programming like my beloved Java we're always creating objects with new this and new that as you've seen here well the factory pattern says hold
up let me handle that for you think about creating different types of users in your app you got admins you got regular users you got moderators here's what that could look like without a factory yeah not the cleanest thing under the sun if type admin user create new admin or type moderator user new moderator or else user new regular user but if we were to follow the factory pattern boom that's it that's it we use user Factory we create an admin id1 Nam John as you can see up here and then the type is thrown
into a switch statement so all of that messy Logic the object creation logic is hidden in the factory class and all we have to do to create a new user is this it's just like when you're driving down the road and you look at a factory oh that's a that's a car plant you know that cars pop out of there but you don't see all of the intricacies and complexity and this and that of what's going on inside the factory because you don't need to know any of that or at least you don't need to
focus on that every single time you see a car come out of there so just like with the code you have you have the macro idea of what's being popped out instead of worrying about all of the logic every single time you need to create a new user and then for us if we want to change how an ad is created just update the factory need to add logging every time a moderator is created update the factory want to start pulling and reusing user objects update the factory you want to use factories every single time
you see yourself using that new keyword all over your code base the downside of a factory is that you're adding another layer of abstraction but is that really a bad thing I don't think so the real downside in my opinion is that there annoyingly coupled H they are very dependent on the factory class but the flexibility you get in return overall it it's worth the trade-off for sure and your code becomes way more maintainable because all of the creation logic is in the same place in that factory class it manages the complexity just like twin
gate manages the complexity of dealing with vpms for accessing development environments and internal tools and just to be clear twin gate the sponsor of this portion of today's video is not a a VPN it's a modern replacement if you will here's the difference instead of exposing your services to the public internet or dealing with slow VPN connections twin gate creates secure direct connections to exactly what you need when you're working remotely as a developer that could be your staging environment internal tools Cloud resources whatever you get instant access with Incredible performance while everything stays completely
PR you can manage everything as code with their terraform provider it has a kubernetes operator for service deployment and the setup is remarkably simple in short twin gate allows developers to securely access work resources remotely via zero trust network access with the Speed and Performance you need for development work this means that you can easily control exactly who has access to what which is perfect for development teams want to learn more and try it out well click the link in the description and see how twin gate can transform your development workflow okay now on to
the second category that was a creational category this is the structural structural patterns starting with facade the facade pattern is exactly what it sounds like putting up a a pretty front to hide everything behind it and you may be saying well isn't this kind of similar to what we just discussed the factory hides all of the stuff inside the factory remember creational patterns are for object creation structural patterns are how objects relate to each each other and the facade pattern it is kind of odd how it's like it's a pattern I mean it makes sense
it's fully detailed they uh it is a design pattern with specific implementation patterns and use cases but really it it's really just good programming technique I guess all of these are good programming technique but this one is really hard to miss anyway uh let me move on to my analogies you guys know how much I love my analogies so if you're watching this video you like how I EXP explain things trying to put them into layman's terms because that always helps me out make sure you subscribe because that's how I explain everything if you don't
like it you're not going to like the rest of my videos but you know how when you order something online and you put in your card d da and you click buy now and then well I mean magically everything else happens well behind that simple button a payment is being processed there are inventory checks there are shipping calculations fraud detection but you as the customer you don't really care I mean you care about fraud detection things of that nature but you don't really care about everything that's going on behind the facade right behind the buy
now button that's that's the idea here it's it's kind of just a really fancy word for encapsulation yeah I kind of like that it's a fancy word for encapsulation let's look at some code so without the facade oh Lord help us this is what it's like so new payment processor stored over here new inventory system stored over here so on and so forth everything that we just disced us and then we run through if fraud Checker if inventory system if payment processor bless your heart if you got to maintain all this and that is without
a facade and you'd have to write this every single time however with the facade you create a new order facade and you may be wondering well what happened to all of these aspects in the facade well all of that code is within our order facade class payment processor payment processor as you can see here then we have our instructor and then we have place order which has all of our if statements here to check through everything and this is all the code you need to write because we're using a facade where again if you weren't
you'd have to write this every single time use a facade pattern when you just have a mess of complex subsystems that you need to simplify so for programming it's exactly like that we get the outward appearance of the interface or class that we're interacting with and it hides all of that information all the complexity within it so we don't have to worry about it every single time the only real downside of a facade or at least the downside that I would like to point out is when it could become a god object I'm what's called
a Celestial sweetheart a Celestial like a god small G son knowing too much and doing too much but compared to spreading the complexity everywhere I'll take the trade-off and you're probably using facades all the time without realizing it think of a HTTP client you just call fetch API users and you get your data right you don't care about TCP connections or retry logic or header parsing or any of that low-level stuff and I mean this is actually built into programming languages like an array list in Java it's hiding all sorts of array resizing complexity behind
a clean interface array list that's the beauty of facades they're everywhere in good code next is the adapter pattern which is a very easy one simple one to understand because we deal with adapters in real life all the time have you ever had a laptop that you wanted to connect to a TV that it didn't have like any like what the 2016 MacBook Pro it didn't have the proper ports so you used an adapter to go from a USB port to a HDMI port the naming of these design patterns is not supposed to be complex
it is very simple very um intentional very specific it it's an adapter and you want to use the adapter pattern when you're integrating third-party libraries or apis that don't quite match what your code expects so let's say the third-party weather API gives us information in Celsius in kilometers and I've created this weather API interface however our app is expecting Freedom Units of Fahrenheit and Miles without an adapter we'll do something like this create implementation of thirdparty API with class thirdparty weather API that implement weather API which is the getting our Celsius and getting our kilm
per hour and then in order for it to work in our app we would have to come down here create the new thirdparty weather API stored in weather API and then do the conversion from Celsius to Fahrenheit conversion from kilometers to miles and well that's what you'd have to do every single time however with the adapter we implement the weather app which is what has temp F and speed miles hour we'd create class weather adapter that implements weather app which has our freedom units in Constructor private weather API weather API and then in our Constructor
we say hey weather API interface we need you because we're going to get the temp c from that weather API we're going to convert it to Fahrenheit and it'll be all done in this method and same idea with kilometers to miles and all of this is being done within the class so when we want to get that information from our API we can do something like this all of the logic is hidden right here and then we're using that information oh is it above 75 oh it's hot oh is the wind speed above 10 mph
oh it's windy that's it so instead of changing your code everywhere and putting that logic every single time you need to use celsius and kilometers from the weather API or if it was a library trying to modif modify the entire Library good luck with that all you have to do is wrap it in and adapt sounds like I was almost saying rapid Dash wrap it in and adapter rapid in an adapter say that five times fast the only thing is it can get real tedious trying to make an adapter for everything best case scenarios that
your library and API match up with what your app needs but that's again that's not always the case and an adapter is always going to be better than having all of this logic spread throughout your entire code base and what's interesting about the adapter pattern I don't know if this is just my mind trying to connect things but since it's all about making different implementations work together through a common interface it's kind of like the application of the strategy pattern which is the first behavioral pattern we'll be discussing and just to clarify again the structural
pattern is how objects interact with each other behavioral patterns is exactly how they behave how they communicate with one another so let's talk about the strategy pattern think about how you get to work some days you may drive to work other days you may ride your bike to work other days you may ride the bus I I live in the middle of nowhere where we don't have public transportation nor am I close enough to ride my bike anywhere so I just I do drive everywhere but this is how I imagine city Folk do it oh
let me change it up today let's take the subway today let's take the train let's let me drive let me bike let me walk I don't know regardless what I'm trying to get at is uh you have a common goal you need to get from point A to point B you are trying to get to work you just have different strategies of going about it one is driving one is walking one is taking the bus that's exactly what this pattern is all about so without the strategy pattern you have the efl's nightmare you have a
class of commuter that's you you're the commuter and you are going to work and if you're transport car then you know you got to start car check gas navigate traffic parking garage all of the logic is here else if you're taking the bus this logic taking the bike that logic and then this keeps growing with each transport type however with the strategy pattern you just have an interface of Transport strategy and then you implement transport strategy in the specific class foreset strategy so car strategy you put in the car specific logic bus strategy same idea
bike strategy same idea so that way once you come down here and actually create a better Commuter class within the class you can set the strategy and then just have one single if statement that utilizes whatever strategy you set up here and runs this Logic for for all of them and again instead of having if else if else if and then keep on going for walking and Subway and this and that so the usage would be just like this with the better Commuter you would store that in commuter and then you could set your strategy
to car strategy and then just call go to work and it'll do all of that logic with thing go to work and then if you need to switch the strategy let's do bike strategy instead that's how we're going to set the strategy and go to work with bike strategy and that's where again each individual strategy has their specific logic within it it is just so much cleaner this is how you need to be writing code don't don't don't if else if else if else if El every single time because the beauty of the strategy pattern
is that it it allows you to define a a family of algorithms you put each into its own class and then make them completely interchangeable or in other words it's just a fancy way of saying programming at an interface level letting you swap implementations without you needing to change any of your code you just make the thing into an interface and you do all the logic below the interface when should you use it all the time if you got different ways of doing the same thing then the strategy pattern is going to be your best
friend it follows the open closed principle perfectly you can add new strategies without touching any existing code and again that is just creating a new class that implements the transport strategy is whatever strategy we have car bus bike walk strategy and implement the transport strategy have your logic within that class the the walk strategy class you're good the downside downside is that you end up with a bunch of classes but that's a whole lot better than if eling if eling if eling and having the logic here and then having 20 different small classes all with
their own L statements like I was just saying yeah I'm going to take the strategy pattern every day of the week and I know I know this is going to hurt some feelings because I know a lot of y'all are just if elsing if elsing everything you know who you are don't you know who you are all right the last but not least the Observer pattern and I'm going to use the you a YouTube example because you're watching this on YouTube and you're the Observer to my video but let's focus on like notifications when I
upload a video and you're subscribed actually when you click the Bell make sure you click the Bell make sure you're subscribed all that when you click the bell I upload a video you get notified that's it the Observer pattern in code we'll go over it lets objects subscribe to events that happen to other objects objects subscribe to events that happen to other objects so here's the code without the Observer you have a class called user account this is the class to create you the user and right down here you create the user account array and
you are put in an array with all of the other subscribers of this video channel right and then when I upload a video what do I want to do I want to bloop through users and notify you somehow that 500 600,000 of y'all I don't think so so instead we use the Observer so that subscribers get notified automatically same idea but we create an interface called subscriber and then we're going to create a class we I just called it better video channel just so I can have two video channel classes in here and it is
the same idea we have the subscriber array and then you are added when you subscribe or removed when you unsubscribe and then when I upload a video we would notify with the title of the video to the subscribers down here as you can see this is our private notify method and we pass in the title so that it notifies all of my subscribers each of my subscribers I should say with that information does that make sense I think it's a good example it's just a little as long as you know how to read code you
know exactly that it makes sense otherwise you're going to have to Loop through millions and millions of people for many other channels every single time you upload a video which is not very uh performant so this in code like you see how it works in the code here but this could be like uh servers looking for system errors or monitoring for them so anytime there's a system error boom it gets notified or a component listening for uh State changes so remember object subscribing to events that happen to another object now there is one gotcha though
if you uh well if you go overboard on a vent you could enter into what is known as event callback hell where one event triggers another event which triggers another event and then all of a sudden you're wondering why your app is sending you a notification from 3 weeks ago but use responsibly The Observer pattern is is an amazing way to handle the uh if this happens do that and there you have it like any good tool it's knowing when to use each one so study them use them practice to get them in GR in
your head for more programming Concepts and developer stuff explained with too many analogies make sure you subscribe to the channel I'll see you in the next one