Typescript Design Patterns (Object-oriented programming) | Xavier Decuyper | Skillshare

Playback Speed


  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x

Typescript Design Patterns (Object-oriented programming)

teacher avatar Xavier Decuyper, Keep learning!

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

6 Lessons (48m)
    • 1. Introduction

      1:50
    • 2. Decorator Pattern

      9:10
    • 3. Render observer

      12:09
    • 4. Render facade

      7:00
    • 5. Render adapter

      5:46
    • 6. State Pattern

      12:25
  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

673

Students

--

Projects

About This Class

Object oriented design patterns help you create more robust and flexible software. In this course I will show you how to use these patterns in TypeScript.

Design patterns are best practices that will help you solve common problems in programming. There is no need to solve a generic problem that has been solved many times before.

Simple example: how do you write a system that allows user to order a product and customize some of its features? There are many possible solutions but they probably won't be as flexible as using a decorator pattern.

941f6ef0

Meet Your Teacher

Teacher Profile Image

Xavier Decuyper

Keep learning!

Teacher

Hello, I'm Xavier, a passionate developer with a wide interest. I have worked on countless of projects and I'm always looking for new and exciting stuff. Through Skillshare I want to pass along some of my knowledge to you!

See full profile

Class Ratings

Expectations Met?
    Exceeded!
  • 0%
  • Yes
  • 0%
  • Somewhat
  • 0%
  • Not really
  • 0%

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. Introduction: Hi, everyone. My name is Savi, and this is the first video off the typescript design pattern Siris. In the upcoming videos. I will show you how to use these patterns in typescript to fall along with the Siri's. You'll need some basic knowledge of objects or into programming and typescript. If you don't know anything about typescript, check out my syriza about it here. So what are designed 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 air so generic that they're 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 extend ability and flexibility of mind. There will also help you avoid common mistakes and when decide patterns air 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 an implement design patterns in typescript. I'll show you patterns like decorator, strategy, observer facade and adapter. I'll also keep adding videos through the Siris in the future, so make sure to subscribe to my channel so you won't miss a beat. 2. Decorator Pattern: Hi, everyone. My name is Soviet and in this video will be taking a look at how you can use the decorator pattern in typescript. Just one remark before we start The decorated pattern has nothing to do with the decorators feature in typescript. It's a bit confusing, but decorators and typescript are basically like annotations in Java. In this video, we will discuss the pattern and not the feature, a decorator pattern. It's 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 diesel cars. A customer has to choose between either the model s or the model acts nothing too fancy. But these guards 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 of the price in this example. The options that doesn't give you decorate your car. Hence the name decorator pattern. You basically take a base class, say the model s. Instead, she ate it and then wrapped 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 or set the truth. 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 work. So I've created two classes, the model s and Model X class. And both of these have description, and they have a method costs which returns the base costs of this carbs. So the model as costs $73,000 while the model x coast $77,000. So the first thing that I'm gonna do is that when create an abstract class car that both of these classes will extend. So let's start by creating an absurd class core eso 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 order model acts, never just a generic car. Now this class will have a description, as both of these cars already have, which is a type string. It should also have a method get description which should return a string. And the method will look like this. Returned this thought description pretty simple. And we will also create an abstract, an abstract method cost that will return a number. So now I'm gonna go to the model s and say that this extends the car class and I'm gonna 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 acts, for example, we might choose the enhanced autopilot. So for this, I'm going to create a new abstract class and I'm gonna call this class car options and administrated this extents car. This will be very important later on, so a car option will decorate a car. So we're gonna keep a reference through the card that we decorate gonna call that decorate 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. OK, so that's our class for car options. Now let's create an actual car options. Let's create a class, let's say, enhance autopilot. That's one of the options that you want to offer on our Tesla's. And we're gonna say that this extends core 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 overwrite. So the 1st 1 that I have to override is get description. So I'm gonna do that right here. I'm going to say, Well, we're going to return. Ah, the description of the car that we decorate and then we're gonna appends the name of her options were going to say, enhanced auto pilot. Okay, we're gonna do the same for the cross here. We're going to say that the costs off this option equals the cost of the decorated car, plus the cost of this option. So, for example, we're going to charge $5000 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 ah constructor. And this constructive will receive Ah, 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 super. Okay, so that said, when we create a new enhanced autopilot option, we're gonna give it an instance of car, which could be a model s or a Model X. And then when we asked the cost of this option, we're just gonna take the model s order, Mom acts that were decorating. We're gonna take that cost and add $5000 to it. So let's make another one, get a copy and paste this class here. And let's say we will also want to offer people rear facing seats. So I'm gonna add rear facing seats here. We're gonna keep the decorated car. We're gonna keep the constructor, we're gonna keep description. But now we're gonna change it. We're going to say rear facing seats because that's what this option is all about. And we're gonna charge $4000 for the rear facing seats. So how do you know use his decorator pattern? Well, we're going to start by creating on instance of a Tesla's. 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 say, I want the rear facing seats rear facing seats, and I'm gonna pass along my Tesla's so that it can decorate my car. So let's now take a look at what it looks like. If we run this, we're going to say, Consul locked my tesla dot costs, and we're gonna log the description of my tessalit get description. So let's open up the terminal now. Oops. And let's run to compose 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 ask costs $73,000 plus the $4000 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 auto pilot. Well, all we have to do that. Say my Tesla equals new autopilot to enhance out about. Sorry, and give it again my Tesla's so we can wrap around that object. And now, if I run it again, our prices bumped up to 83,000 and the description of her 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 off the decorator pattern. Here we have four components. We have to absolute classes. The first absolute class is called component, and it has an operation. In my example, this was the absolute car class with the operation costs. We also have the abstract decorator class. In my example, this was the absolute 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 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. 3. Render observer: Hi, everyone. My name is Javier and in this video will be taking a look at how you can use the observer pattern in typescript. So what is this pattern about? While 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 than you probably already know this pattern you've probably used on click or on change handlers to detect when the user clicks on something or when he changes some text in 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 and visual studio code. And in this video we're going to ride a weather station. So I've already set up a weather station class and a temperature displayed 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 law weather station, New temperature measured and then it outputs the temperature and then it also sets the temperature attributes. That's pretty simple. Now, in this example, we call the weather station a subject because other classes can monitor that class and we call the temperature display on observer because that one observes another object temperature display observes changes in the weather station. So we're going to start by creating two interfaces for subjects and observers. So I'm gonna create one first subjects. Animals are gonna create one for observer. Now, the subject needs three methods. The 1st 1 is Register Observer, and we're gonna get on 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 those that it should notify the temperature display of any changes. We're also going to 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 not 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 on observer class and pass along the temperature. So let's now implement these interfaces. So I'm going to 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 what we're gonna say implements 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 1st 1 is Register Observer. Now I want to do here is we want to keep track of this observer that we get here as a parameter. So I'm gonna create a new private attributes for a weather station. I'm gonna call this observers, and this is gonna be an area off observer objects, and I'm gonna initialize it as an empty area. So when someone wants to be notified of changes in our weather station while then he calls the register observer with the reference to himself. And all that we're gonna do is we're gonna say this dot observers thought push. Oh, so we're gonna keep track of this observer. That's everything that the register observer meant that you 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 area. So we're gonna fetch the index by saying this that observers dot index off. Oh, so we're gonna look up where he is in our area and when we know his location that we're going to say this dot observers dot spice and we're gonna take away the element at the index. So that's the remove observer method. Still pretty simple, pretty straightforward, were just manipulating on air in 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 four loop. So we're gonna in arrayed over all the observers. I'm going to say observer off this 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 want to notify observers. So we're just going to say Notify? We're gonna say this, Doc, Notify observer and actually, let's let's make this plural because there could be multiple notified 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 that we can go and implement our observers. So in this case, we have temperature display going to say that this implements the observer in their face. Then it's gonna complain again because I need to implement some methods. There we go. And temperature display has only one method. That's update. So whenever the temperature updates, we want to do some logic in here. But I'm just gonna fake some logic and Mr gonna say I'm just gonna log something to the council. I'm going to say temperature displayed. I need to update my display for example, and then your logic would go here. Now, that's not enough. We need to actually say to the weather station that are temperature display wants to be notified of changes. So let's do that right now. Let's create a private attributes here. We're going to say that we observe the subject. It should be a type subject. And we're also gonna create a constructor in which we're going to receive the weather station, which is a subject, and we're just gonna keep track of this 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 weather station dot register observer, 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 not create another observer. This is the beauty of this pattern. You could have many observers that will be notified when a single element in your code base changes. This case is her weather station. So let's say also want to have a fan, so I'm gonna copy paste the temperature display. I'm going to create a class fan. I'm gonna leave the private attributes 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 to fan toe automatically turn on when the temperature is above 25 degrees Celsius, for example. So here I'm going to say, Well, if the temperature is hired in 25 Celsius, then we 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 consul lock. 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 some real logic and not just a council lock. 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 off our temperature display. It's a 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 fans were going to 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 going to simulate a temperature change. So I'm going to say that the temperature is now 20 degrees Celsius and then we're gonna doublet Kate this line, and after a while we're gonna say, Oh, the temperature rises to, for example 30 degrees. Okay, let's take a look at what will happen. So I'm gonna run the typescript compiler to compile this to JavaScript, and then I'm going to run it and no, 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 going to 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 my display and the fan says, 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 recreate 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 observer. So it has register observer, unregistered 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 called the notify function on inch and every one of them. So that was it for this video. If you like to make sure to subscribe to my channel, it really helps me out a lot. If you want to learn more about typescript or typescript designed patterns, check out the next videos in these Siri's. 4. Render facade: Hi, everyone. My name is Sylvia, and in this video we will be taken 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 theatre set up. So I've created a class for blue rate player for an amplifier, some lights, a TV and a popcorn maker. Now let's assume that I want to start watching movie every time we want to watch a movie. I have to do certain things have to turn on my blue ray player, have to press play on it. I have to turn on my amplifier, have to set the volume, have to set the source of my amplifier, 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 the right now. I'm going to start by creating a new class. 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 blue ray player, which should be of type, literate 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 Buckler ***. Okay, there we go. Now, the constructor of the home theater facade will receive all thes devices and instance of all of these devices. So I'm going to repeat some of the code here. There we go and all what we're going to do in the constructor is we're gonna keep track of these devices were going to say this amp equals the amp that we got in the constructor. This blue ray equals the blue Re that we got in the this 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 and want to set up all of my devices to watch a movie, while in this case I'm gonna create a method called Watch movie and this Met that is gonna prepare my entire set up for watching a movie. So what we can do is we can ask the popcorn maker to turn on, and the popular makers should start pumping 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 going to set the source of the amplifier Two blue ray thes air fake methods. By the way, you have to substitute thes for your own implementations. And then we're gonna set the volume of the amplifier. So in this case, we're gonna turn up to 11. And last but not least, we have to turn on my blue Ray player and we're gonna have to start playing the movie. Okay, so that's the facade methods for when I want to start watching a movie. And I could do the same for when I'm actually done watching movies so I can say, Well, public and movie. And then we could do some other stuff like we concern on the public. Or you can turn off the popcorn maker. We can turn off the amp. And we can turn off the TV and turn off the blue rape. Okay, there we go. So now we've actually placed all of this complex behavior in the set up process. We've placed that behind a single method of Assad, 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 going to start by creating a blurry player, an amplifier, some lights it would be and the Buckhorn maker. And then we're gonna create a new home theater facade someone to call mine Home theater. It's a new home theater facade. This will receive all of the instances that were just created. So Blue Ray players, 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 set up process that is involved and start watching a movie. And the nice thing about this is that you can use this single line throughout your code, and you can keep all of this set up coat centralized in the single class. That is the strength of the Assad 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 re type this entire set up 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 that all you have to do is change of these instructions, and then it's changed in all the places off your coat. So this was a very simple example of how the saut pattern can be implemented in typescript . I really hope you like 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 want to learn more about design patterns in typescript, make sure to check out the rest of these. Siri's Thank you very much for watching, and I'll see you in the next one. 5. Render adapter: Hi, everyone. My name ISC Soviet. 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 coat. You can compare it to adapters in real life. See, you're traveling from the United States to Europe. If you want to charge your devices, you'll need an adapter to convert the European Wall outlet to us one. In this case, the adapter should implement the European plug and expose us blood 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 Patton works. I've created an iPhone seven class and a Google pixel class. Now, the iPhone uses a lightning port to charge while the group pixel uses micro USB, so save you want to charge your 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 the airport. So for Android, that will be the method used 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 going to create a new class, and we will call this class Lightning to micro USB adapter. And I'm going to say that this implements the android interface. So if I want to make the iPhone compatible with micro years, be, then they have to make an adapter that implements micro USB, but internally can convert it to lightning. So the first thing that we do is we need to implement the missing elements from Android. We're going to do that right now. There we go. So we get a method used 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 my career's be so I'm gonna keep track of an iPhone device, and we're gonna receive that iPhone device through our constructors are conservative will receive an iPhone, which is a type iPhone, and we'll just keep track of it. So will 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, so we need to map it to something that the iPhone understands. So I'm going to say, first, we're gonna write something to the council, so we're gonna say, Want to use my career's be converting to lightning, Okay? And then we're going to say this, not iPhone device, use lightning. So even though the iPhone is not compatible with micro USB, it only has used lightning. We can make it compatible with this adapter. Dis adaptor will implement the my career's be function and internally translated to something that the iPhone can understand. Now. This example it's really simple. We just call another method, but in a more complex code base, it could just this well be that you need to convert some arguments and doom or complex set up work. So how do you use this interface? Well, I'm gonna create an instance of the iPhone seven here, So I'm going to say is a new iPhone seven. And if I want to charge it with my career's be 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 It's constructor. And now we can ask the charge adapter to use my career's be So let's take a look at what happens when I run this. 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. No, but yes, let's see what happens. Okay, so notice that it says Okay, we want to use my Korea's B, 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 adapted class handles translating the micro USB code into lightning. And so again, in a real code base, this could be much more complex. You might need to change the order of the arguments were 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 want to learn mawr 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. 6. State Pattern: Hi, everyone, my name misc. Soviet. 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 dot 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 through the order being prepared state. In these states, the user has the option to cancel, but it should not be possible to move directly toe order, ship 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 number. Order has a state that can be ordered being prepared, order shipped, payment pending canceled order and so on and so on. So to start with, I'm going to 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 shipping 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 will give our order Class A property called the current state. And that's of course, gonna be of type states. And we're also gonna create a center that is going to receive states. And then we're gonna say this current state equal state and we're gonna create a getter as well get state, which is going to return a state object. And it's just going to return this stop current state. So 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 a class I'm gonna create payment pending states. That class obviously implements our state interface that we've just defined, and visual studio code will complain. I'm going to implement the missing elements. And there we go. We now have got are pending state Uh, class. I'm also gonna give it a constructor because here we have a new order property, but we need to fill that in. So when we're creating a new payment pending state, we're going to receive an order object in R Constructor and we're just gonna keep track off this order. So I'm gonna create three more classes of this, just gonna copy and paste this. We're going to implement these methods later on, so we have payment pending. We also have ah canceled order State. We also have a order being prepares states and I'm gonna create it. Order shipped states At that point in this state, everything is finally order a ship. You cannot cancel it anymore. you can verify your pain anymore. That has already happened. So I'm going to 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. 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 going to say this that canceled order equals new counseled order State, and we're gonna give it a reference off 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 it state by default. That's gonna be the payments pending state. So I would create a new order. We're going to 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 going to say, canceling your unpaid order. And when that's done, we have to set the state of our order to the cancel order State. There we go. So let's continue on. If the payment is pending, we assure us how can verify the payment. So we're gonna say consulate log, Damon, Fair fight. Shipping soon, for example. I've never been a copy. This line that we're gonna move to ST along, we're gonna set the state of the order, not to the cancelled order state, but through the order being prepared state. Now, if your payment is spending, 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 payments 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 cancel order State. If your order is cancelled, 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 their payment anymore. If your order has been canceled and we also cannot ship in order that was canceled so we can say order cannot ship. It was canceled. So onto 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 canceling your order. And then we're gonna copy the same line here. There we go. But we're gonna set the state to or cancel order state. So for verify payments, we cannot really verify our payment because we've already done that at this point Already verified your payments. And when the order is being prepared, we can, of course, ship it. So we're going to say shipping your order now and then we're gonna move the state along. We're going to say that the order is now in the order shipped states, Let's now go on to the final order the order ship State. If an order is shipped, you cannot cancel it. You cannot verify the payment anymore and of course, if the chip you cannot re ship it again. So these methods should be just empty methods or methods that tell the user that it cannot do any of these things can cancel or any ships. You cannot verify it payments because your order has already shipped hoops and you cannot ship it again because it is 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 word, verify payment chip 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 long. So let's now see how you actually use it. So I'm gonna start by creating an order. And so I'm gonna say Wonder new order. And let's just write a message through 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 going to see order dot Get state that we're gonna call the constructor and we're gonna eco the name of the constructor so we can see which states the order is currently in. So let me run this coat right now to show you. So we're gonna run the typescript compiler, and then we're gonna run it in No gs. And there you go. When we create a new order or order is in the payment pending state. That's pretty August. So that say, at this point, our system tries to ship the order, so I'm going to say order dot get states and we want this order to ship. What suit? Right now. Let's compile it again. And now it says we can ship the order when payment is pending and the order state stays at payment pending, so it hasn't moved to the ship. Order stayed because that's actually not allowed by our process. Okay, so that's not allowed. Let's do verify payments and let's run it again. And this time you can see payment has been verified shipping soon, and the state over order has changed toe order being prepared. Okay, so we can do more stuff, but I cannot verify it again. If I do it again and I'll run it, it will say that My payment has been verified shipping soon. But when I run verified 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 three or four. Run it now it will say the payment is verified worshipping your order now and the current state of my order is in the order Ship 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 is 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 Bannon is ideal to keep track of a specific process in this case, shipping and 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 at methods to my state's. 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 like this video. Make sure to subscribe to my channel if you want to learn more about typescript designed patterns and, as always, I'll see you in the next video.