 Hi everyone, my name is Xavye and this is the first video of the TypeScript Design Pattern series. In the upcoming videos, I will show you how to use these patterns in TypeScript. To follow along with this series, you will need some basic knowledge of object-oriented programming and TypeScript. If you don't know anything about TypeScript, check out my series about it here. So what are design patterns and why would you want to use them? While many problems in programming have already been solved by others and don't require you to solve them again. Some of these solutions are so generic that they are called a design pattern. The benefits of using design patterns are clear. First of all, you don't have to spend time and energy solving problems that have been solved many times before. Secondly, design patterns help you increase the quality of your code because these patterns were designed with extendability and flexibility in mind. They will also help you avoid common mistakes. And when design patterns are used in teams, it allows developers to quickly understand other people's code because they'll likely recognize some of these patterns. In this series, I'll show you how to use and implement design patterns in TypeScript. I'll show you patterns like decorator, strategy, observer, facade and adapter. I'll also keep adding videos to this series in the future, so make sure to subscribe to my channel so you won't miss a beat. Hi everyone, my name is Xavier and in this video we'll be taking a look at how you can use the decorator pattern in TypeScript. Just one remark before we start. The decorator pattern has nothing to do with the decorator's feature in TypeScript. It's a bit confusing but decorators in TypeScript are basically like annotations in Java. In this video, we will discuss the pattern and not the feature. A decorator pattern is useful for when you want to allow objects to have different options. I'll explain with an example. Let's assume that you're in charge of writing the ordering software for Tesla cars. A customer has to choose between either the Model S or the Model X, nothing too fancy, but these cars have many different options that you can choose. A customer might pick the improved autopilot or the smart air suspension or maybe both. Every option has a different effect on the price. In this example, the options that Tesla give you decorate your car, hence the name decorator pattern. You basically take a base class, say the Model S, instantiate it and then wrap many options around it. This is much better than giving your Model S class a list of properties like has smart air suspension and then calculating the total price by checking if these properties are set to true. So let's dive into the code and take a look at how you can develop such a system with the decorator pattern. Okay, so here I am in Visual Studio Code ready to show you how the decorator pattern actually works. So I've created two classes, the Model S and the Model X class. And both of these have a description and they have a method cost, which returns the base cost of this car. So the Model S costs $73,000 while the Model X costs $77,000. So the first thing that I'm going to do is I'm going to create an abstract class car that both of these classes will extend. So let's start by creating an abstract class, car. So we're creating an abstract class here because there should be no instance of car. There should only be an instance of the Model S or the Model X, never just a generic car. Now this class will have a description as both of these cars already have, which is of type string. It should also have a method get description, which should return a string. And the method will look like this return this dot description, pretty simple. And we will also create an abstract, an abstract method cost that will return a number. So now I'm going to go to the Model S and say that this extends the car class and I'm going to do the same for the Model X and say that it also extends the car class. Okay, so next up we will define a class for all of our options that we can choose for our Model S and our Model X. For example, we might choose the Enhanced Autopilot. So for this, I'm going to create a new abstract class and I'm going to call this class car options. And I'm going to say that this extends car. This will be very important later on. So a car option will decorate a car. So we're going to keep a reference to the car that we decorate. We're going to call that decorated car. And I'm also going to say that this should override the get description method, which returns a string. And it should override the cost method, which should return a number. Okay, so that's our class for car options. Now let's create an actual car option. So let's create a class. Let's say Enhanced Autopilot. That's one of the options that you want to offer on our Teslas. And we're going to say that this extends car options. And Visual Studio Code will complain now. It will say that I need to implement some elements of car options here. So I'm going to click on that and it will generate the methods that I need to override. So the first one that I have to override is get description. So I'm going to do that right here. I'm going to say, well, we're going to return the description of the car that we decorate. And then we're going to append the name of our options. So we're going to say Enhanced Autopilot. Okay, now we're going to do the same for the cost here. We're going to say that the cost of this option equals the cost of the decorated car plus the cost of this option. So for example, we're going to charge $5,000 for the Enhanced Autopilot. Now there's one more thing missing. We need to fill in this decorated car property. So I'm going to make a constructor. And this constructor will receive a car, which will be of type car. And we're just going to say this dot decorated car equals car. And of course, we also have to call it super. Okay, so that's it. When we create a new Enhanced Autopilot option, we're going to give it an instance of car, which could be a Model S or a Model X. And then when we ask the cost of this option, we're just going to take the Model S or the Model X that we're decorating. We're going to take that cost and add $5,000 to it. So let's make another one. I'm going to copy and paste this class here. And let's say we also want to offer people rear-facing seats. So I'm going to add rear-facing seats here. We're going to keep the decorated car. We're going to keep the constructor. We're going to keep the description. But now we're going to change it. We're going to say rear-facing seats because that's what this option is all about. And we're going to charge $4,000 for the rear-facing seats. So how do you now use this decorated pattern? Well, we're going to start by creating an instance of a Tesla. So I'm going to say my Tesla equals a new Model S. And now I'm going to say my Tesla equals a option. For example, new, let's say I want the rear-facing seats. Rear-facing seats. And I'm going to pass along my Tesla so that it can decorate my car. So let's now take a look at what it looks like if we run this. I'm going to say console log my tesla.cost. And we're going to log the description of my Tesla. Get description. So let's open up the terminal now. Oops. And let's run the TypeScript compiler on this. And let's also run it in Node at the same time. There we go. All right, so here we can see that my Tesla will cost $77,000. That will be the Model S with rear-facing seats. So that seems about right. Our Model S costs $73,000 plus the $4,000 for the rear-facing seats gives us $77,000. Now let's say the customer also wants another option. Let's say he wants the enhanced autopilot. Well, all we have to do is say my Tesla equals new autopilot, new enhanced autopilot, I'm sorry. And give it again my Tesla so we can wrap around that object. And now if I run it again, our price has bumped up to $82,000 and the description of our car is now Model S with rear-facing seats and enhanced autopilot. So that's a simple example of how you can use the decorator pattern to decorate classes in TypeScript. Now I just want to end the video by showing you the UML diagram of the decorator pattern. Here we have four components. We have two abstract classes. The first abstract class is called component and it has an operation. In my example, this was the abstract car class with the operation cost. We also have the abstract decorator class. In my example, this was the abstract class car options. Then we have concrete classes for both of these. So in my example, the concrete components were Model S and Model X. And the concrete components for the decorator were the rear-facing seats and the enhanced autopilot. As you can see in this diagram, the decorator also keeps a reference to the component that it is decorating. And it also overrides the same operation. So that was it for this video. I hope you liked it and if you did, make sure to subscribe to this channel so you won't miss new videos. And if you want to learn more about design patterns in TypeScript, check out the rest of the videos in this series. Hi everyone, my name is Xavier and in this video we'll be taking a look at how you can use the observer pattern in TypeScript. So what is this pattern about? Well, often when one part of your application changes, other parts need to be updated. This is the kind of problem that you can solve with the observer pattern. Now, if you have already developed a web application, then you probably already know this pattern. You've probably used onClick or onChange handlers to detect when a user clicks on something or when he changes some text in a form. In this video, we'll take a look at how you can implement the observer pattern yourself. So let's get started. Okay, so here I am in Visual Studio Code. And in this video, we're gonna write a weather station. So I've already set up a weather station class and a temperature display class. Now it's pretty obvious that the temperature display should update every time that the weather station records a new temperature. So the weather station has a private attribute temperature, which is of course a number, and then it has a set method for temperature, and then it just outputs to the log weather station new temperature measure, and then it outputs the temperature, and then it also sets the temperature attribute. So that's pretty simple. Now with this example, we call the weather station a subject because other classes can monitor that class. And we call the temperature display an observer because that one observes another object. Temperature display observes changes in the weather station. So we're gonna start by creating two interfaces for subjects and observers. So I'm gonna create one for subject, and I'm also gonna create one for observer. Now a subject needs three methods. The first one is register observer, and we're gonna get an observer object in here. What this allows us to do is it allows our temperature display, for example, to register itself as an observer with the weather station. So the weather station then knows that it should notify the temperature display of any changes. We're also gonna create a method remove observer, just in case that we want to stop being notified of changes in the temperature, and then we're gonna create a method notify observers because if a change happens in our subject, it should notify all its observers. Okay, so that's it for subject. Let's now move over to observer. This one should have only one method that's update. And in our case, when we update, we will pass along the temperature to a subject. So if the temperature changes in the weather station, it will call the update method on an observer class and pass along the temperature. So let's now implement these interfaces. So I'm gonna say that the weather station implements the subject. And this is gonna throw an error because I have three methods that I need to implement. So I'm gonna say implement missing methods. There we go. So here we've got register observer, remove observer and notify observer. So we're gonna implement them one by one. The first one is register observer. Now what we wanna do here is we wanna keep track of this observer that we get here as a parameter. So I'm gonna create a new private attribute for a weather station. I'm gonna call this observers. And this is gonna be an array of observer objects. And I'm gonna initialize it as an empty array. So when someone wants to be notified of changes in our weather station, well, that he calls the register observer with a reference to himself. And all that we're gonna do is we're gonna say this dot observers dot push O. So we're gonna keep track of this observer. That's everything that the register observer method should do. Now let's do the remove observer. If someone wants to be removed as an observer, well, then we first have to look where he's positioned in our array. So we're gonna fetch the index by saying this dot observers dot index of O. So we're gonna look up where he is in our array. And when we know his location, then we're gonna say this dot observers dot splice. And we're gonna take away the element at the index. So that's the remove observer method. Still pretty simple, pretty straightforward. We're just manipulating an array here. Now comes the notify observers. Every time that something changes in our weather station, we should notify all of our observers. So we'll need a for loop. So we're gonna iterate over all the observers. I'm gonna say observer of this dot observers. Just loop over them. And we're gonna call the update method on each observer and we're gonna give it our current temperature. Okay, so that said, there's just one more thing that we need to do. Every time that our temperature changes, we're gonna call the set temperature method. And then we also wanna notify observers. So we're just gonna say notify, we're gonna say this dot notify observer. And actually let's make this plural because there could be multiple notify observers. There we go. And also gonna change it here in the interface. Okay, so that's everything that we need to do in our weather station. Now we can go and implement our observers. So in this case, we have temperature display. We're gonna say that this implements the observer interface. Then it's gonna complain again because I need to implement some methods. There we go. And temperature display has only one method and that's update. So whenever the temperature updates, we wanna do some logic in here, but I'm just gonna fake some logic. I'm just gonna say, I'm just gonna log something to the console. I'm gonna say temperature display. I need to update my display, for example. All right, and then your logic would go here. Now that's not enough. We need to actually say to the weather station that our temperature display wants to be notified of changes. So let's do that right now. Let's create a private attribute here. We're gonna say that we observe a subject. Should be a type subject. And we're also gonna create a constructor in which we're gonna receive the weather station, which is a subject. And we're just gonna keep track of the subject. So we're gonna say this subject equals the weather station. And then we're gonna register ourselves with the weather station. So we're gonna say weatherstation.registerObserver and we're gonna register ourselves as an observer because our temperature display wants to know when changes happen to the temperature. Okay, so that's it for the temperature display. Let's now create another observer. This is the beauty of this pattern. You can have many observers that will be notified when a single element in your code base changes. In this case, it's our weather station. So let's say I also wanna have a fan. So I'm gonna copy paste the temperature display. I'm gonna create a class fan. I'm gonna leave the private attribute here intact. I'm also gonna leave the constructor as is. And then we're gonna change the update method. So the first thing that we're gonna do is we're gonna write some logic in here. What I want is I want the fan to automatically turn on when the temperature is above 25 degrees Celsius, for example. So here I'm gonna say, well, if the temperature is higher than 25 Celsius, then we need to turn on the fan, for example. So we're gonna say it's hot here, turning myself on. And then you obviously here you want some real logic, not just the console log. And if it's colder than that, we're gonna say fan, it's nice and cool. And we're gonna turn myself off. There we go. And again, here should come some real logic and not just a console log. Okay, so that's it. Now, how do you use the observer pattern? Well, you just create instances and pass references along. So the first thing that we're gonna do is we're gonna create our own weather station. So we're gonna say new weather station. There we go. And then we're gonna create an instance of our temperature display. Gonna say new temperature display. And we're gonna give it our weather station so it can ask the weather station to be kept in the loop. We're gonna do the same for the fan. So we're gonna say fan is new fan. And we're also gonna give it a reference to the weather station. There we go. And now we're gonna play with it a bit. So we're gonna say weather station. We're gonna simulate a temperature change. So we're gonna say that the temperature is now 20 degrees Celsius. And then we're gonna duplicate this line. And after a while, we're gonna say, oh, the temperature rises to, for example, 30 degrees. Okay, let's now take a look at what will happen. So I'm gonna run the TypeScript compiler to compile this to JavaScript. And then I'm gonna run it in Node to see the output. Now, as you can see, when I say set temperature 20, our weather station says the new temperature measurement is 20. And immediately followed by that, the temperature display is gonna say, oh, I need to update my display. And the fan will say, it's nice and cool. I can turn myself off. That's exactly what we want. We made a change to our weather station and it automatically notified all of the observers that are subscribed to changes in the weather station. So when we set the temperature to 30, the weather station does the same thing. It says that the new temperature measurement is 30 degrees. And this triggers the temperature display and the fan to update themselves. So the temperature display now says, well, I need to update my display. And the fan says, ooh, it's hot here. I'm gonna turn myself on. So this is a simple example of how you can use the observer pattern. So let's quickly recap in what we have learned in this video. This is the UML diagram for the observer pattern. And as you can see, we have an interface for an observer and we have an interface for subject. Then we create concrete observers that have the notify method. In our case, that was the fan and the temperature display. On the subject side, we also create a concrete subject, although that's not shown here on the UML. And that one is responsible for keeping track of all the observers. So it has register observer, unregister observer and notify observers. And you can also see that whenever you call the notify observers method, it should run over all of its observers and call the notify function on each and every one of them. So that was it for this video. If you liked it, make sure to subscribe to my channel. It really helps me out a lot. If you wanna learn more about TypeScript or TypeScript design patterns, check out the next videos in these series. Hi everyone, my name is Xavier and in this video, we will be taking a look at how we can use the facade pattern in TypeScript. This pattern is used to hide a lot of complexity behind a single method. I'll use a home theater system as an example because those can be quite complex to control and set up for a particular use case. So let's take a look at the code. Okay, so here I am in Visual Studio Code and I've already created classes for some of the devices in my home theater setup. So I've created a class for Blu-ray player, for an amplifier, some lights, a TV, and a popcorn maker. Now let's assume that I wanna start watching movie. Every time I wanna watch a movie, I have to do certain things. I have to turn on my Blu-ray player. I have to press play on it. I have to turn on my amplifier. I have to set the volume. I have to set the source of my amplifier. I have to dim the lights. I have to turn my TV on and I have to turn on the popcorn maker and start popping some popcorn. Now that's a lot of complexity and it's also not practical if there are multiple places in my code where I want to start watching a movie because then I would need to copy and paste all these instructions. Instead what we can do is we can create a facade. This is a class that will hide all the complexity behind a single method. So let's do that right now. I'm gonna start by creating a new class and I'm gonna call my class home theater facade. And this class will have an attribute for each of the devices that we want to control. So in my case, it's a Blu-ray player which should be of type Blu-ray player. We should have an amp type amplifier. We should have some lights. We should have a TV and of course a popcorn maker which should be of type popcorn maker. Okay, there we go. Now the constructor of the home theater facade will receive all these devices, an instance of all of these devices. So I'm gonna repeat some of the code here. There we go. And all what we're gonna do in the constructor is we're gonna keep track of these devices. So we're gonna say this amp equals the amp that we got in the constructor. This Blu-ray equals the Blu-ray that we got in the constructor. Okay, there we go. Now we're ready to set up our actual facade. So let's say that there are multiple places in my code where I want to start watching movie. I want to set up all of my devices to watch a movie. Well, in this case, I'm gonna create a method called watch movie. And this method is gonna prepare my entire setup for watching a movie. So what we can do is we can ask the popcorn maker to turn on. And the popcorn maker should start popping some corn. There we go. We should also dim the lights. We should definitely turn the TV on because otherwise we won't be able to watch our movie. We're gonna also turn on the amplifier. And we're gonna set the source of the amplifier to Blu-ray. These are fake methods. By the way, you have to substitute these for your own implementations. And then we're gonna set the volume of the amplifier. So in this case, we're gonna turn it up to 11. And last but not least, we have to turn on my Blu-ray player. And we're gonna have to start playing the movie. Okay, so that's the facade method for when I want to start watching a movie. And I can do the same for when I'm actually done watching a movie. So I can say, well, public end movie. And then we can do some other stuff like we can turn off the popcorn maker. We can turn off the amp. And we can turn off the TV. And turn off the Blu-ray. Okay, there we go. So now we've actually placed all of this complex behavior in this setup process. We've placed that behind a single method, a facade if you want. So how do you use it? Well, very simple. You start by creating an instance of each of your devices that your facade needs. So I'm gonna start by creating a Blu-ray player, an amplifier, some lights, a TV, and the popcorn maker. And then we're gonna create a new home theater facade. So I'm gonna call mine home theater. I'm gonna say new home theater facade. This will receive all of the instances that we've just created. So with Blu-ray player, some lights, a TV, and the popcorn maker. All right. And now we can call one of the methods in our facade to start watching a movie, for example. Just say watch movie. And the facade will take care of all the complex setup process that is involved in start watching a movie. And the nice thing about this is, is that you can use this single line throughout your code. And you can keep all of this setup code centralized in a single class. That is the strength of the facade pattern. The facade pattern is a really simple pattern, really straightforward, but it allows you to keep your code short and to the point, and it prevents you from having to retype this entire setup over and over again. Also, the facade pattern is very future-proof because if one day you decide to add a device to the mix, then all you have to do is change up these instructions, and then it's changed in all the places of your code. So this was a very simple example of how the facade pattern can be implemented in TypeScript. I really hope you liked this video, and if you did, make sure to hit the thumbs up button or to subscribe to my channel. It really helps me out a lot. If you wanna learn more about design patterns in TypeScript, make sure to check out the rest of these series. Thank you very much for watching, and I'll see you in the next one. Hi everyone, my name is Xavier, and in this video we'll be taking a look at the adapter pattern. This pattern allows you to make different classes with different interfaces to work together without changing their source code. You can compare it to adapters in real life. Say you're traveling from the United States to Europe. If you wanna charge your devices, you will need an adapter to convert the European wall outlet to a US one. In this case, the adapter should implement the European plug and expose the US plug for you to use. So let's take a look at how you can implement that in TypeScript. Okay, so here I am in Visual Studio Code, and I've already created two classes to show you how the adapter pattern works. I've created an iPhone 7 class and a Google Pixel class. Now, the iPhone uses a lightning port to charge while the Google Pixel uses micro USB. So say we want to charge our iPhone with a micro USB cable that we need an adapter to change the port to lightning. So the first thing that I'm gonna do is I'm gonna create two interfaces for each of these devices. So I'm gonna make an interface for iPhone and I'm gonna make an interface for Android devices. And both of these interfaces will receive a method that is tied to their port. So for Android, that will be the method use micro USB. And for the iPhone, we will add a method use lightning. And of course, the iPhone implements the iPhone interface and the Google Pixel implements the Android interface. Okay, so far, so good. So now we're going to define the adapter. So I'm gonna create a new class and I'm gonna call this class lightning to micro USB adapter. And I'm gonna say that this implements the Android interface. So if I wanna make the iPhone compatible with micro USB, then I have to make an adapter that implements micro USB but internally can convert it to lightning. So the first thing that we need to do is we need to implement the missing elements from Android. We're gonna do that right now. There we go. We got a method use micro USB. Now before I implement this, we also need a device. And so in this case, we want to make our iPhone compatible with micro USB. So I'm gonna keep track of an iPhone device. And we're gonna receive that iPhone device through our constructor. So our constructor will receive an iPhone, which is of type iPhone. And we'll just keep a track of it. So we'll say that this iPhone device equals the iPhone that we got in the constructor. Okay, so through this adapter, we can now use the micro USB function, but we need to convert it still. We need to map it to something that the iPhone understands. So I'm gonna say, first we're gonna write something to the console. So we're gonna say want to use micro USB, converting to lightning. Okay, and then we're gonna say this dot iPhone device use lightning. So even though the iPhone is not compatible with micro USB, it only has use lightning, we can make it compatible with this adapter. This adapter will implement the micro USB function and internally translate it to something that the iPhone can understand. Now this example is really simple. We just call another method, but in a more complex code base, it could just as well be that you need to convert some arguments and do more complex setup work. So how do you use this interface? Well, I'm gonna create an instance of the iPhone 7 here. So I'm gonna say is a new iPhone 7. And if I want to charge it with micro USB, I'm also gonna create a charge adapter, which is of course a new lightning to micro USB adapter. And I'm gonna give it my iPhone in its constructor. And now we can ask the charge adapter to use micro USB. So let's take a look at what happens when I run this. So I'm gonna open up the terminal here and I'm gonna run the TypeScript compiler on adapter and simultaneously I'm gonna run it in Node.js. Let's see what happens. Okay, so notice that it says, okay, we want to use micro USB, but we need to convert it to lightning because that's what our iPhone uses. And then our iPhone says, hey, I'm using the lightning port. So what's great about the adapter pattern is that I don't need to change the iPhone class to be compatible with micro USB. I only create a new class, an adapter class that handles all the translations. So in this case, the adapter class handles translating the micro USB code into lightning. And so again, in a real code base, this can be much more complex. You might need to change the order of the arguments or you might need to convert them to other types or you might need to use many classes to accomplish something like this. I hope this simple example illustrates how you can use the adapter pattern in TypeScript. If you wanna learn more design patterns in TypeScript, make sure to subscribe to my channel. Thank you very much for watching this video and I hope to see you in the next one. Hi everyone, my name is Xavier and in this video we're going to take a look at how you can use the state pattern in TypeScript. This pattern is used to keep track of the state of a process. In this video, I'll use an order on amazon.com as an example. Here's a simple diagram showing what the process could look like. It's a bit simplified, but it will do for this example. Each arrow represents an action that the system can take and each box represents the state of the order. It starts when the customer places an order. At that point, we should verify the payment. After it is verified, it moves to the order being prepared state. In these states, the user has the option to cancel but it should not be possible to move directly to order shipped state or to any of the previous states. So let's take a look at how you can implement a system like this in a way that is flexible and future proof. Okay, so here I am in Visual Studio Code and I've already created a simple class for our order and I've given it a constructor, pretty basic. Now our order has a state that can be order being prepared, order shipped, payment pending, canceled order, and so on and so on. So to start with, I'm gonna define an interface for the state. So I'm gonna call my interface state, obviously. And each state is going to keep track of the order it is assigned to and each state will have three methods to move it to another state. So in case of an order, we want to be able to cancel our order, verify the payment of our order or ship an order. So I'm gonna write that down. I'm gonna say cancel order, verify payments and ship order. Now it's very important that all states have these methods. Next up, we'll give our order class a property called current state. And that's of course gonna be of type state. And we're also gonna create a setter that is gonna receive a state. And then we're gonna say this.currentState equals state. And we're gonna create a getter as well, getState, which is gonna return a state object. And this is just gonna do return this.currentState. So now I'm gonna create our first state. So when you place your order with Amazon, your order has a payment pending state. Amazon still has to verify your payment method and charge your credit card. So I'm gonna create that class. I'm gonna create payment pending state. That class obviously implements our state interface that we've just defined. And Visual Studio Code will complain. I'm gonna implement the messing elements. And there we go. We now've got our pending state class. I'm also gonna give it a constructor because here we have an order property, but we need to fill that in. So when we're creating a new payment pending state, we're gonna receive an order object in our constructor. And we're just gonna keep track of this order. So I'm gonna create three more classes of this. You're just gonna copy and paste this. We're gonna implement these methods later on. So we have payment pending. We also have a canceled order state. We also have a order being prepared state. And I'm gonna create a order shipped state. At that point in this state, everything is final. Your order has shipped. You cannot cancel it anymore. You cannot verify your payment anymore. That has already happened. So I'm gonna scroll up and I'm gonna go to the order class. And I'm gonna create four properties in this order class, one property for each of the possible states that it can be in. So I'm gonna fast forward the video, but this is what I'm gonna do. Okay, and in the constructor, we're gonna initialize each of these states. So we're gonna say this.canceledOrder equals newCanceledOrderState. And we're gonna give it a reference of this current order. And again, I'm gonna fast forward the video here. Okay. And when we create a new order, we're gonna set its state by default. That's gonna be the payment pending state. So when we create a new order, we're gonna place it in the payment pending order state. That's pretty simple. So now we can start implementing our actual states. So let's start with the payment pending state. If our payment is pending, we can still cancel it. So we're gonna override this method and we're gonna say cancelling your unpaid order. And when that's done, we have to set the state of our order to the canceledOrderState. There we go. So let's continue on. If the payment is pending, we sure as hell can verify the payment. So we're gonna say console.log payment verified, shipping soon, for example. And then we're gonna copy this line that we're gonna move the state along. We're gonna set the state of the order not to the canceledOrderState, but to the order being prepared state. Now, if our payment is pending, can we ship it? Well, no, because we need to wait until the payment has been verified. So all we're gonna do here is we're gonna say we cannot ship the order when payment is pending. So at this stage, when your order is in payment pending state, you can call, you can ask it to ship the order, but the system will just say, you know, I cannot do that and it will stay in the payment pending state. So let's go to the canceledOrderState. If your order is canceled, you cannot really cancel it again. So you're gonna say your order has already been canceled. And then we're gonna do nothing more. Same thing goes for verify payment. You cannot verify your payment anymore if your order has been canceled. And we also cannot ship an order that was canceled. So we can say order cannot ship it was canceled. So on to the next one, order being prepared state. If your order is being prepared, you can actually still cancel it. Well, with Amazon, you can cancel the order just until the moment that it's been shipped. So we can say cancelling your order. And then we're gonna copy the same line here. There we go. But we're gonna set the state to canceledOrderState. So for verify payment, we cannot really verify our payment because we've already done that at this point. Already verified your payment. And when our order is being prepared, you can of course ship it. So we're gonna say shipping your order now. And then we're gonna move the state along. We're gonna say that the order is now in the order shipped state. So let's now go on to the final order, the order shipped state. If an order is shipped, you cannot cancel it. You cannot verify the payment anymore. And of course, if it's shipped, you cannot reship it again. So these methods should be just empty methods or methods that tell the user that it cannot do any of these things. You cannot cancel, already shipped. You cannot verify payment because your order has already shipped. Whoops. And you cannot ship it again because it has already shipped. So that's basically how the state pattern works. You create an interface with all the methods that move your state along. So cancel order, verify payment, ship order. And then you make a class for each state that your order can be in and you implement all of these methods. And these methods are responsible for moving the state of your order along. So let's now see how you actually use this. So I'm gonna start by creating an order. And so I'm gonna say order new order. And let's just write a message to the screen that says the order state. And then we're gonna display the state. So we're gonna cast it to an object, to any object. We're gonna say order dot get state. Then we're gonna call the constructor and we're gonna echo the name of the constructor so we can see which state the order is currently in. So let me run this code right now to show you. So we're gonna run the TypeScript compiler and then we're gonna run it in Node.js. And there you go. When we've created a new order, our order is in the payment pending state. That's pretty obvious. So let's say at this point, our system tries to ship the order. So I'm gonna say order dot get state. And we want this order to ship. Let's do that right now. Let's compile it again. And now it says we cannot ship the order when payment is pending and the order state stays at payment pending. So it hasn't moved to the shipped order state because that's actually not allowed by our process. Okay, so if that's not allowed, let's do verify payment and let's run it again. And this time you can see payment has been verified shipping soon and the state of our order has changed to order being prepared. Okay, so we can do more stuff but I cannot verify it again. If I do it again and I run it, it will say that my payment has been verified shipping soon but when I run verify payment again, it will say, hey, you've already verified your payment and the order is again in the order being prepared state. So just to complete the cycle, after verifying the payment, we should ship the order. So if I run it now, it will say the payment is verified, we're shipping your order now and the current state of my order is in the order shipped state. Now let's say I want to try and cancel my order now. Well, then it will say that that is not possible because it has already shipped. So you can see payment verified, we're shipping your order and then you cannot cancel at this point anymore because your order has already shipped. So that was it for this video. I hope that this simple example made clear how you can use the state pattern. The state pattern is ideal to keep track of a specific process, in this case, shipping an order to the customer. It's also very flexible because at any time I can add more states to my system and all I have to do is add methods to my states. It's also very secure because I can define what is possible and what is not possible at each given state. So in this example, there is a rule that says once an order has shipped, you cannot cancel it anymore. So thank you very much for watching. I hope you liked this video. Make sure to subscribe to my channel if you want to learn more about TypeScript design patterns. And as always, I'll see you in the next video.