YTread Logo
YTread Logo

Design Patterns in Plain English | Mosh Hamedani

Jun 07, 2021
Welcome to my ultimate course on

design

patterns

. I'm Mosh and I'm very excited to be your instructor. Let me give you a quick overview of what this course is about and what you need to know before you start. You will learn to

design

reusable and extensible object-oriented software. In order to take this course, you must have at least three months of programming experience. It doesn't matter what language you are familiar with. You just need some basic programming experience. You are familiar with basic object-oriented programming concepts, such as classes on interfaces, which will be great but not necessary.
design patterns in plain english mosh hamedani
I'll give you a basic overview of these concepts in the next section, before we get started I want to set expectations on this. Of course, we are not going to work on any algorithm. You won't see me working with loops or Eve statements nor will we implement complex logic which is not the purpose of this course. I have covered all the algorithmic topics in my data structure as algorithms. Of course, we're not going to create an application either, but rather talk about object-oriented software design. We'll talk about how you should structure your classes and how these classes should collaborate.
design patterns in plain english mosh hamedani

More Interesting Facts About,

design patterns in plain english mosh hamedani...

Our focus will be on creating reusable and extensible software. software that can be easily extended The techniques that we are going to cover in this course are extremely important and every software engineer who works with object-oriented systems should master this, so I am very excited to be your instructor. Design

patterns

are one of my favorite topics. and many of you have been waiting for this course for a long time, so let's jump in and get started. You might be wondering what artistic design patterns, well design patterns are elegant solutions to repeating problems in software design, for example, you might want to implement undo. mechanism in your application which is a repetitive problem in software design right now, we have a couple of different patterns to implement the undo function, one of them is the moment pattern, so a design pattern shows you how you should structure your classes and how these classes should speak.
design patterns in plain english mosh hamedani
Now in this series we will explore 23 design patterns that were originally documented in the 90s in the book called Design Patterns Elements of Reusable Object-Oriented Software. The book was written by four authors known as Gang of Four. We very often refer to these patterns as Gang of Four patterns. The Gang of Four patterns include 23 design patterns in three categories. Creational, structural and behavioral. Creation patterns are about different ways of creating objects. Structural patterns are about the relationships between these objects and behavioral patterns. They are about the interaction or communication between these objects in the first part of this series we will talk about behavioral design patterns and by the way these design patterns do not represent all the patterns in your work, there are many unofficial and undocumented patterns.
design patterns in plain english mosh hamedani
There are some that can be useful in certain situations, but these 23 design patterns are the classics that every software engineer should understand. One of the benefits of design patterns is that they help us communicate with other developers on a more abstract level, for example, you can tell your coworker, we can use the command pattern to improve this code. You can simply use the name of the pattern to communicate the idea. You don't have to write a lot of code to express that idea. Another benefit of studying and understanding this design. patterns is that it makes you a better designer, you will learn how to create reusable, extensible and maintainable software no matter what programming language you use or what type of applications you create and finally, another benefit of learning design patterns is that they help you learn and wear. new frameworks faster one of the questions I usually get asked is how do you learn several things quickly?
I'm telling you I'm not a genius yes I have years of experience in fact I started programming when I was seven years old and now 37 but one thing that I think has helped me enormously is understanding these design patterns because I see these design patterns used in various frameworks and libraries, so every time I learn a new framework it seems familiar, it's just a different syntax that I have to memorize, so these are the benefits of learning design patterns as opposed to other courses in books that teach you design patterns. design as a list of recipes to follow.
In this course I will teach you the art of designing object-oriented software. I'm not going to give you a catalog of design patterns arranged alphabetically. I've specifically arranged the patterns in this course to teach you several important concepts, so although you can jump to a specific pattern to learn more about it, it's best if you take the course. from the beginning to the end because throughout the sections I will talk about various principles and if you skip them you will miss a lot, so if you want to get the most out of this course, watch all the sections in order.
It is short and simple and you can see it in half an hour or less. If you have taken any of my courses, you know that I do not waste your time with long, slow and repetitive explanations. Also, in this course I will be using Java, but you do not need to be a Java developer to take this course. In the next section, I'll give you a quick overview of Java syntax so you can easily understand the code we write. If you use Python or C Sharp or some other language, you can take the concepts from this course and apply them again in your programming language. favorite programming.
Our focus is on the art of designing object-oriented software, not on a particular programming language. Now, if you're a Java developer, I still encourage you to check it out. The next section, although it may seem a little basic to you because in the next section I am going to talk about the essential concepts of object-oriented programming, such as encapsulation abstraction inheritance and polymorphism, many developers don't really understand this. concept correctly, so see you in the next section. In this section, I'll give you a quick tour of Java and the essential object-oriented programming concepts you need to understand to take this course we'll be talking about. about classes interfaces encapsulation abstraction inheritance polymorphism and UML, which is the graphical notation that we will use throughout this course.
If you know Java, you can skip the first video or two where I create a new project and show you how to work with a class, but I highly recommend that you watch all the other lessons, especially the lesson on interfaces, because interfaces are one of the concepts most misunderstood in Java and many programming languages ​​also be sure to check out all the other lessons such as Encapsulation Abstraction Inheritance and Polymorphism which are extremely important, I want to make sure we are on the same page and that you really understand which are these concepts. If you don't understand them properly, you won't be able to understand design patterns, so let's jump in and get started.
Just in this course I will be using IntelliJ, which is a very popular Java IDE, but you can use any ID you prefer if you want to use IntelliJ and code with me. We can get it from jetbrains comm slash idea slash download it comes in two editions, the definitive one, which is paid and the community one, which is free and open source here in IntelliJ, let's create a new project, so we select Java on the left, then we select create project from template, we want to create a command line application and then we will give this project has a name, let's call it design patterns here, we need to specify the name of the base package.
A package in Java is a container for one or more classes in some languages ​​like C Sharp, it is called and namespaced, so here we must write the name of the base package. convention we use reverse domain name my domain is a code with calm matching so here we have calm that code with Marsh this is just a convention it doesn't mean you have to have a domain name registered on the internet you can write anything here, Alright. As you can see, every Java project has this main main dat Java file and in this file we have a class with exactly the same name.
This class is declared in this package. Communicate that code with wash, so the package declaration at the top of the file determines. where this class will be defined, now in this class we have a method called main, both this method and this class are declared as public, this means that they are accessible from anywhere in this code base. We will talk about this later in this section. The main method is declared as static, this means that we can call this method directly without having to create an instance of the main class. void is the return type of this method which means that this method will not return a value and here in parentheses we have the parameters of this method in this case we have a single parameter which is an array of strings called args if we run this program from the command line and pass some different arguments, we can capture those arguments using the string array.
Well, now in Java we use curly. braces to represent a block of code and by convention we put the left brace on the same line in some languages ​​like C sharp we put the left brace on a new line but this is not conventional in Java so let's go back to where it was so this They are the basic concepts of a Java program. Next, I'll show you how to create and use classes. Okay, let me show you how to work with classes, so in the project window we expand the project folder. Here we have the source folder. where we have all the source code for this project and its folder, we have our base package which contains the main class.
Now we right click on the package name and add a new class. Let's call this user in this class that we can have. padding or attributes to store data and methods, let's declare a field to store the users name, so the name of the public string and end it with a semicolon, so in Java we end our declarations with a semicolon , now technically, this is bad practice for declaring fields as public. I'll talk about this later in this section, for now we're going to declare everything public, so string is the type of this field and it's called name.
Now we can go to the main class and create a new instance of the user class, so we write. user user is equal to new user, so we declare a variable called user, the type of variable is our user class and here we set this as a new instance of the user class, once again we end the declaration with a dot and comma, now using the dot operator we can access the field and the methods of this class so we can set the name field to Marsh and once again we finish this with a semicolon. Please note that in Java we use double quotes to surround the strings, now we can print this field in the terminal then we have the system class this class has a field called this is an object which has a method called print line this is like a console to type the c-sharp line now here we can pass the user that name and then we can run this program using ctrl + R there you have it so here is my name in the terminal beautiful now we can specify the name when creating a new user like this that we go back to the user class we add a constructor a constructor is a method that is called when we create a new instance of a class so here we write public then we write the name of the class and then we had parentheses this is where we can declare parameters, then we add our curly braces, so let's add a parameter here called string name, now we can set the name field to the value of the name parameter, however both the parameter and the field have the same identifier, so if we write name equals name, the java compiler thinks that we are referring to this name parameter, so on the left side we need to prepend this with this dot, so we are saying set the name field of the current object with the name parameter value, so this is a reference to the current object, if we write this point we can see all the fields and methods in this class, okay, now let's go back. to the main method when creating a new user object we can pass the name to it, we don't need to set it explicitly and then we can print it to a terminal to run it and we get the same result as before.
Now let's add a method on this. class, so we start with public, we don't want to return a value, so we use void, we call this method, say hello and here we will print a message like hello, my name is and then we can combine this string with the name field value now in this context we don't have a name parameter, so we don't have to use this keyword, we can just reference the name field directly. Now, back in the main method, instead of printing a user's name, we can calluser dot, say hello, then run and we get this message, this is how we can create and use classes in Java.
One of the important concepts in object-oriented systems is coupling, which determines to what extent a class is coupled or dependent on another class for For example, here in the main class we are using the user class, so the class main is coupled or depends on the user class so if you change the user class the main class might be affected we have to change it or at least we have to recompile and redeploy let me show you so I will come back to the user class and I will introduce a new parameter in this constructor, let's say an integer H, so we have changed the user class, now the main class is broken, we can't compile this code, we have to pass this argument here, so this is the problem with coupling, let me show you another example in the user class, let's add a script before this message, now in the main class, we don't have a breaking change in our code compiler, perfect.
However, because we have changed the code in the User class, this class needs to be recompiled and that means that all classes that depend on this class also need to be recompiled. This is a very simple program, we only have two classes, but what if? We had hundreds or thousands of classes and many of them were highly dependent on each other in an application like that, if you change the class we could end up with a lot of cascading changes. An application built this way is really hard to change, hard to extend, let me give you a metaphor. think about your car, if you get a flat tire, you only need to replace that tire, you don't need to replace this steering wheel or the engine, right, your car is an example of a loosely coupled system, the components of your car work together, but they are not tightly coupled nor depend on each other, so you can replace individual parts independently, our applications should be the same way, but how can we create loosely coupled applications using interfaces?
And that's what I'm going to cover next. Interfaces are one of the most misunderstood. constructs in Java and many other programming languages. I talked about this in detail in the second part of my definitive Java course which lasts about 4 hours, but let me ex

plain

very briefly that an interface is a contract that specifies the capabilities that a class must provide. let me give you a metaphor: imagine you want to open a restaurant, you need a chef, it doesn't matter who the chef is, so you don't depend on a particular chef, you only depend on someone who can play the role of chef. chef someone with certain abilities this is an example of a loosely coupled system.
Now I told you that an interface is a contract that specifies the capabilities that a class must provide, so in this example we can represent the role of a chef with an interface and the actual chefs with classes that implement the chef interface, so This is the idea behind interfaces with interfaces we can create loosely coupled applications. Let me show you this in code, so let's say you want to create a tax calculator. Tax calculation is complex and the rules can change. From year to year we may have one calculator for the year 2019 and another for the year 2020, just as we may have different people playing the role of chef in a restaurant, but what do all tax calculators have in common?
They probably have a method called calculate tax we can represent this with an interface so in this package let's add a new class first change the type to interface and call it tax calculator so this is just a contract that specifies the methods that our calculator classes must implement so here we had a float method to calculate taxes note that we only have one method declaration so we end the declaration with a semicolon. This method has no body, no implementation. If you have curly braces here, we get a compilation error, so this interface says: Hey, if you want to create a tax calculator class, that class must have a method with this signature.
Okay, let's add a real tax calculator in this project, so we add a new class which we call tax calculator 2019. Now here we write implements tax. Calculator we now have a compilation error because we have not implemented the tax calculation method in this class. We can put the cursor here, press the toggle and select implement methods. Intellij added the calculate tax method in our class, but don't worry about this override. this is called annotation. I talked about this in the second part of my definitive series on Java. For now, all that matters is that this class has a method with this signature.
Here we can return one. Now let's create another calculator, so once again we add a new one. class we call it tax calculator 2020 once again we say it implements the tax calculator and then the toggle implements beautiful methods now in the year 2020 and we can go back, so now we have two different implementations of this interface in our application, instead To work with these concrete implementations, we should work with this interface, this is called programming in an interface, so anywhere we need a tax calculator in this program, we are going to work with this interface, for example, we can go back to the main class, let's add a public static method.
I made the static one, so we can call it directly from the main method. Okay, now this method should return a tax calculator, so here we are using our interface. Let's call it get calculator. For now, we will return a new 2019 tax calculator now in our main method. We will call the get calculator method and store the result in a variable called calculator, so in this method we have a dependency or coupling to this interface. Now this interface is very simple, it is very lightweight, all it has is a method called calculate tax, as long as we keep the signature of this method exactly like these, we are not going to have a breaking change, this is how we achieve loose coupling , so with this programming style, if we go to our 2019 tax calculator and let's say we add a new method here public float calculate insurance, we have changed this class, but this change will not affect our main method here because we are programming in a interface, not in a concrete implementation now, if you've been paying close attention and you might say, but swamp, we're being new here.
We created a tax calculator 2019 so if you make any changes in this class then this class has to be compiled again and that means the main class has to be compiled too. True, but this is a very simple example to demonstrate this concept in a real business application. Now we are going to write code like this, we use what we call a dependency injection framework which gives us real implementations of an interface, so in our code we work with interfaces now, if this concept is new to you, don't worry, We're going to talk about this more and more throughout the course so that you learn the basics of interface classes.
In the next few videos, we will talk about the four basic principles of object-oriented programming. It is easier to ex

plain

it using a real example, so in this project I am going to add a new class called account, this represents a bank account, a human is a field to store the balance of this account, so the balance public float now with this implementation we can go to the main class and create a new account. Now we have repeated the class name twice, so it is better to use the VAR keyword here. Now with this implementation we can set the balance to any amount, we can set it to a positive or negative value, but what if negative balances are not allowed? in our application we should not be able to write code like this;
In other words, we should not allow other classes like the main class to change the state of this object directly, they should not be able to change the data in this object, so To solve this problem we go back to our account class and replace this keyword public with private. public and private are examples of access modifiers. Many other object-oriented languages ​​have the same concept. Now in the main class we have a compilation error because we can't. accessing balanced field from outside this class is hidden inside this class so inside this class we can use it anywhere but we can't access it from outside this class but what if we really need to change the balance, how are we going to be able to do it?
Do that right here in the account class, we can add a public void set balance method, we give it a parameter called balance and here we set that balance to balance now because we have a method here in this method, we can do some kind of validation. So before setting the balance, we can make sure that it is a positive value, so if the balance is greater than zero, then we can set it now. A better implementation is to raise an exception or error if the balance is an invalid value, but let's not worry about that.
We don't want to do too much Java in this course, we will stick to the basics, this is what we call a setter, a method that is used to set the value of a field in the same way, we can have a getter, so if you want read the value of the balance field, we can call a method called getbalance so that the public float gets the balance and here we return the value of the banners field. This is the principle of encapsulation in action, so encapsulation is really about grouping together data and methods that operate on data within a unit or a class and hide the values ​​or state of an object within the class, so with this we can create robust applications, we can prevent our objects from going into an invalid state, so this is the principle of encapsulation now.
We can take this to the next level instead of establishing this balanced method. It would be better if it had methods like withdraw and deposit, so instead of sending the balance to some kind of random value, it is better to record some kind of transaction so we know when. we deposit or withdraw money from this account so let's add a new public null deposit method we give it a parameter called amount and then we can set this balance to this balance plus amount or in java we can use the augmented assignment operator so that we can rewrite the statement this way: the balance plus equals the amount.
These two statements are identical. In this case we don't even need the disk keyword because our parameter is called quantity so it's better of course here we have to do some kind of validation you also want to make sure that quantity is a positive value so if the amount is greater than zero then we update the bullets similarly we will add a method called withdraw to withdraw money from this account once again we add our validation. Logically, if the amount is greater than zero, then we reduce the balance by this amount. This is a better implementation, so let's remove the set balance now method from the main method, instead of setting the balance to some random value, we can use deposit or withdrawal. methods we created so initially we deposit $10 into this account then we withdraw $5 finally we get the balance and we print it so tap that is our print line statement and here we can call the account that gets the balance, let's run the program and the balance is five dollars beautiful so this is all about encapsulation next let's talk about abstraction now let's talk about the second principle of object-oriented programming abstraction abstraction means that we should reduce complexity by hiding unnecessary details in our classes Let me give you a metaphor think about your TV remote control, this remote control has a bunch of buttons that allow you to work with your TV inside the remote control it has an electronic board and a bunch of transistors etc.
Now we don't work directly with this. transistors its implementation details there is so much complexity there we don't want to worry about that complexity we don't care what happens inside that remote control when we press the power button this is the abstraction principle in action so the abstraction principle says that we should hide the unnecessary details in our classes and this helps us to reduce the complexity, let's say this in the code, let's say we want to implement a class to send emails to our users, so let's add a new class, we call this service mail in this class we need. a method to send an email publicly, unsend email now in a real application here we should have a parameter of type email, but let's not worry about that, in this demo that is part of thesending an email there are a number of things that should happen under the hood we have to connect to a mail server we have to authenticate we have to send the email and then disconnect so we can have a method like connect in this method we just print a message like connect similarly we can have a method called disconnect and here we print this message and let's add one more public null authentication method here we will send our username and password to the mail server so let's say I authenticate now in our method of sending email, we will first call these methods one by one. we will connect, then we will authenticate, then we will send the actual email and finally we will disconnect.
Now let's use this in our main class, so here let's create a mail service and set it to a new one. mail service now look at the interface of this class and by interface I am not talking about the interface construction in Java, I am just talking about the interface of a class like the interface of a remote control, what we see in that remote control or what What we see in this class here we have four methods, but the first three are implementation details. We don't care about this. You don't mind connecting to a mail server.
We don't care about authentication. The only thing that matters to us is capacity. to send an email, these three methods add extra complexity to this class, they make it more difficult for consumers of this class to use this class, so we apply the abstraction principle, go to our mail service and make these methods are now private there. they are implementation details and they are hidden from outside this class once again we make it private and one last time back in the main class look at the interface of this class it has a single method it is much easier to use it is like a remote control with only four buttons have you seen how difficult it is to use one of those remote controls that have 50 buttons you don't really know how to use them if you want to change the volume you have to search everywhere now this kind of mail service has a unique method , your phrase is easy to use and more importantly if we change any of those private methods the main class will not be affected so if I introduce a parameter in this method let's say the timeout is the The only major change we have here is that the main class is not affected because the main class cannot see the connection method.
This is the benefit of applying the principle of abstraction. We can change the implementation details without affecting other classes in our application. We will talk about it below. inheritance let's talk about the third principle of object oriented programming inheritance inheritance is a mechanism to reuse code let's say we want to build a glee framework a gui framework in this framework we want to have classes like text box, button, checkbox, etc Now Onis classes should have some common behavior for example, we should be able to enable or disable them, we should be able to set their focus, we should be able to set their position, etc.
Now when implementing this class, we don't want to implement these behaviors in every class, that's a lot. Code duplication inheritance is a mechanism that allows us to reuse code in our classes so that we can implement all of these common behaviors in a parent or base class and then have all of these other classes inherit those behaviors. Let me show you, so let's add a new class. We are going to call this UI control which is the base or main class for all the widgets in the user interface. Now in this class we want to have the ability to enable or disable a control, so a method called enable and here let's just print a message. called enable now let's create a textbox class so we have a new class called textbox.
We run this class to inherit the code we wrote in the UI control class so here we write extends UI control now you can go to the parent class and create a textbox object so the textbox VAR will send it to a new text box. I'll take a look here. We have the enable method. We don't implement it in the textbox class. We implemented it in the UI control class, but the text box inherited this code. from its father now when we run this program we can see the message enabled beautiful now there is more about inheritance than we can cover in this video.
I have dedicated an entire section on inheritance in the second part of my latest serious book on Java, so if you want to learn more go watch that course next we are going to talk about polymorphism, let's talk about the fourth principle of object-oriented programming polymorphism poly means that many more fins are formed, so polymorphism means many shapes and is basically the ability of an object to take on many forms, let me show you this in code, so continuing with a GUI framework, we want to have the ability to draw each widget on the screen, so in a UI control class let's add a public void draw method.
Now this method will not have an implementation because we don't know how to draw a UI control because the algorithm for drawing a widget is specific to the widget type. drawing a text box is different from drawing a checkbox, so we can leave the implementation empty or better declare this as abstract, so public abstract void draw now we have a couple of compilation errors, the first one is here because An abstract method can't have a body, so we remove the curly braces and end this with a semicolon. This is like a method we declare in an interface is just a method declaration, it has no implementation now because we have an abstract method in this class, we also have to declare this class as abstract, this is like a half baked cake, we can't use it directly, we cannot create an instance of it.
We can't create a new instance of the UI control, we can only extend it now if it goes to our text box class, we see a compilation error because this class has not implemented the drawing method of the UI control, so we place the cursor here, press alt. +enter' and implement methods exactly like we implement methods in an interface, so now we have this public empty drawing method here, let's print drawing a text box, now let's add another class in this project, new class we will call this. checkbox this class inherits all the code from the UI control, so we write extends the UI control, then we make IntelliJ implement the abstract methods of this class, there you have it, now we print the drawing of a checkbox so that each widget knows how to draw itself, now in our main. class let's add a public static method public static empty draw UI control we give it a parameter of type UI control and in this method we call control dot draw now in our main method we are going to call this method so draw your visual control now The UI Control class is the parent or base of the TextBox and CheckBox classes, so each TextBox is a UI Control and each CheckBox is also a UI Control, so so we call this method and we can pass in a new instance of the text box class and we run the program here, we see a text box drawn, if we pass in and check the box, we see a check box drawn, so although in this method we are working with a UI control object at runtime, this object can take many different forms. it can behave like a checkbox, a text box or a button etc.
This is polymorphism in action, so an object can take many different forms. That has to do with polymorphism, so we've covered all the essential object-oriented principles. to talk about um L, which is the graphical notation that we will use throughout this course now that we have covered the basics of Java, let's talk about UML yeoman is short for unified modeling language and is a visual language that we use to model our systems. We will use it throughout this course to represent our classes and the relationship. Here are some examples. This is how we can represent a class in UML, so we have this rectangle at the top and we have the name of the class in the middle. section we have the fields and below we have the methods so here we have a class called form in this class we have a field called position X and the type of this field is integer so after the colon we specify the type of a field or a parameter or the return type of a method, so here we have a method called render, it doesn't have any parameters, that's why we have a couple of empty parentheses and it doesn't return any value, so we don't have a colon. after the method name, that means the return type of this method is null.
Now this minus sign means that this field is declared private. You can see it here and obviously the plus sign means that this is declared as public. Now in this course we are assuming that all our fields are private and all our methods are public, so in future diagrams I will not show the minus and plus signs to keep things simple, this is how we can represent a class in UML now. Let's talk about the three types of relationships between classes, this is what we call inheritance relationship, so this diagram says that the rectangle class inherits or extends the shape class.
You can check that here for the rectangle class to extend the shape. Now we are precisely. In UML, the inheritance relationship is indicated by an arrow with an empty triangle, but in the software I'm using we don't have that arrow, so I'll show my inheritance relationships with an arrow with a filled triangle. Okay, now let's talk. About the second type of relationship between classes, this is called composition relationship and is indicated by an arrow with a diamond, which means that the shape class is composed of the size class in practical terms, which means that in the shape class we have a type size field then the shape class is made up of this size class as another example you can say that the car class is made up of the wheel class because every car has four wheels.
Now in UML we have another type of relationship called aggregation, which is similar to composition, but I don't want to include too much UML in this course; You want to keep things simple and focus on design patterns, so if you have some UML experience you can argue that we should use an aggregation relationship instead of composition here, let's not worry. these subtle details then this is the composition relationship now let's talk about the third type of relationship between classes this is what we call the dependency relationship it is indicated with a dashed arrow which means that somewhere in the form class we have a reference to document class here is an example in shape class we have a method called render and this method has a parameter of type document so document is not a field in this class but it is used somewhere in this class in this case is a parameter but it could also be a local variable defined in the render method, so somewhere in the shape class we have a reference or dependency to the document class.
Well, here are the three types of relationships that we are going to use in this course, inheritance and dependency composition. Hello guys, here I am. I just wanted to let you know that this video you've been watching is the first hour of my Ultimate Design Patterns course. In this YouTube video we talk about two design patterns, but my ultimate design patterns course includes more than 20 design patterns. These are the design patterns. that every software engineer must master, so if you want to learn more I recommend that you enroll in my definitive design patterns course. The first 200 students can get the course at a huge discount.
I'll put the link below if you're interested. The first design pattern we are going to talk about is the moment pattern. We use this pattern to implement undo mechanisms. Let me show you first of all. I'm going to add a new package to this project, so in your package we'll call this boost. is where we are going to write all the code for this pattern. Now let's say we want to build a code editor that supports undo mechanism, so we add a new class in this package, we call it editor. In this class we need to know how to store. the current content of the editor, so the content of the private string we also need a getter and a setter for this field.
Now we don't have to write them manually. We can have IntelliJ create them for us, so we put the carrot in the field name. press alt' + enter' and select create getter and setter for the content, there you have it, so here is our editor class now before we talk about the moment pattern. I want you to spend 10 to 15 minutes thinking about asolution to implement undo function in this. class, then in our main class we should be able to create a new editor, let's say editor equals new editor, then we should be able to set the content of its times, let's say a, B and C, and then we should be able to undo the content.
So I spent 10-15 minutes thinking about a solution to implement this feature. This is extremely important because I want to teach you the art of problem solving. Unlike other courses, I'm not going to give you a UML diagram that says this is the pattern moment and this is how it works. I want to take you through the same thought process that the Gang of Four went through so you understand how and why they came up with a moment pattern, so spend 10 to 15 minutes and come up with a solution when We're done, come back , see the next lesson, here is our editor class with the content field to not keep the screen clean.
I didn't add the getter and setter that we created in the last video. Now the easiest way to solve this problem is by introducing a new field called previous content, so whenever we want to change the value of the content field we store the current value in the previous content field and then change the content field. This is a very simple solution and it works, however with this approach you can only undo once, if you want to be able to undo multiple times we need a list so we need to rename this field to the content above.
Note the plural name and the type of this field will be a list, which is a reasonable solution. What if ever? In future we will introduce a new field as title so our editor window will have a content and title now to support undo mechanism we need another field like previous titles to keep track of all changes in title field now like you. I can see that this solution is not very extensible every time we introduce a new field we need to add an extra field to store all the changes to that field so we need to find a better solution.
Now let me delete these two fields, okay, that's better. so instead of having multiple fields in this class we need a separate class as editor state, this class will be exclusively responsible for correctly storing the state of our editor at any given time, we only have one field in this class called content, in future we will be able to add title and other fields, all these fields will be in a single class, so in our editor class we need to store a list of editor states, so we need a composition relationship between these two classes and that means that we must change the name of this field from the previous one. contents to previous states so that you have a list of editor states inside the beautiful area class now this is a better solution because it allows us to undo multiple times and we won't pollute the editor class with too many fields, it's fine though , this solution is violating a very important principle in object-oriented design which is a washable single responsibility which basically means that each class should have a single responsibility let me give you a metaphor think of a restaurant in a restaurant each person has a specific role they do One thing only, the waiter is exclusively responsible for taking orders, they do not cook for you.
Now imagine a restaurant where the waiter takes your order, cooks for you, goes shopping and also pays taxes. It doesn't make sense that a restaurant like that is very unmanageable we have the same situation in software to build maintainable software we must design our classes in such a way that they have only one responsibility now let's go back to our design our editor class correctly has two responsibilities one of them is The other state management is to provide the features we need from an editor, we should take all the state management work out of this class and put it somewhere else, so we shouldn't have this field inside this class.
Previous states, let's remove this, that means that we are not going to have a the association with the editor of the state class was delayed so much, it is better, we need to introduce a new class called history. This class will have a single responsibility and that would be state management, so it will keep track of changes to the editor's state. Okay, now. In this class we need a field called States, this is the field we previously had in our editor class. Okay, so we have this field here and that means we're going to have a composition relationship with the editor state.
The history class will store 0 or more editor state objects in a list, we also need two methods push and pop with push, we add a new state in the history and pop, delete and return the last state. Now technically we could use a statistic here instead of a list, but that's an implementation detail. Let's not worry too much about that at this stage. Now let's let the area class no longer store state objects internally. should give you two new methods create state and restore state the create state method stores the current state of the editor inside a state object and returns it so we call this method and say hey, save your current state and give it to me, we will get a editor state, then we call the push method of the history class, we say: hey history, save this state, this is how these classes collaborate, okay, the restore method takes a state object and returns this editor to that state so that it resets its fields based on what we have in this state object now look at the type of relationship we have between the editor and the editor state classes.
We have a dependency relationship which means that the editor class uses the state editor because to create the state method an editor returns a state object. Well, congratulations, you came up with your first pattern, this one is called the moment pattern. We use the boost pattern to implement undo mechanisms in our classes. Now here is our representation of the impulse pattern, but if you look at the Gang of Four book or any of the courses or books on this topic, you will see different names for these classes, the editor is called creator, the editor status is called impulse and history is called caretaker.
These are just some abstract names that Gang of Four came up with to demonstrate the concept, it doesn't mean you have to use them to name your classes, always use meaningful names for your classes, so this is pattern time in this pattern, We have three participants or three players, the creator driver and the caretaker, now that you understand this pattern, go ahead and implement it in the code. First of all, the moment a package we add a new class, we call this editor state. Currently, we only need a single field in this class, so the contents of the private string would be good to initialize this field from the constructor so we can press alt + enter' and add a constructor with a parameter there you go, so we have a constructor, this constructor has a single parameter and in the body of this constructor we initialize this field with the value of this parameter, now it is quite simple I would prefer to declare this field as final, this will ensure that once we initialize this field we cannot change it accidentally in our program, so this will add robustness to our code.
Now we also need a getter here to read the value of this field later. Then I'll hit Enter and create getter for the content. That's it, we're done with this class. Now let's go to our editor class. Here we need two new methods, create state and restore, so that the public editor state creates the state when we call this method. The editor will save its current state inside an editor state object and return it, so it returns the new editor state and here we pass the value of the content field. Now let's create the restore method.
It's pretty easy. Void public restoration. We give it a state object and here. set the content field to stay like that but get content as simple as that, the last piece of the puzzle is the history class, so in this package let's add its class, we call it history here, we can use a stack or a list . I don't. I want this course to be wait. Java is specific, so I'll go with a private editor list. State now, what's going on here? Well, this list is an interface that is declared in the Java utility package, so we need to import it first.
Otherwise the compiler doesn't recognize it, we can press alt' + enter' and intellij imported it at the top, so import java.util that list. Now this list interface is a generic interface which means we can use it to create a list of different types of objects we can have a list of strings we can have a list of integers a list of editor states so with these angle brackets we specify the type of objects that we want to store in this list in this case we want to store the state of the objects editor okay, now let's call this field state and set it to a new array list.
What's going on here? Well, I told you that this list is an interface that is declared in the java.util package. In this package we have a class called ArrayList that implements this interface, so you are programming in an interface because the ArrayList class could have other methods that we are not interested in, we only need the functionality that is declared in the list interface. Okay, now here we need two methods: push on pub public void push it. takes a state object from the editor and here we call States and then add state. This will add the state object to the end of the list.
Ok, now the public editor status appears. Here we need to calculate the index of the last element of this list, which is very easy. last index now the list interface has a method called size which returns the number of elements in this list now the index of the first element in the list is 0 so to get the index of the last element we have to get the size and reduce it with 1 now we get the last element, last element or last state which are better states which are obtained with this we can get an element at a given index so let's get this element and then we have to remove it from this list so we call States ready to delete and we pass the last state object and finally we return the last date from this method which is our history class.
Now let's put all this together and see the undo mechanism in action, so here in the main method we first create an editor object and then create a history object, so our history is equal to new history here we set the content to the same time you want to save this date in history so we call the editor which creates the date this will return the current state and we will add it to our history then we call history which pushes with this object a simple stack once again we set the content and right after we save this date to the history, then we set the content to see now here we can undo, so we call history but pop, this will return the status Prima and then we will give it to our editor, so we say: "Hello, before, restore with this date like this now, if you print the current state of the editor, you should take a look at it, so print the editor." but get content, take a look, we get B, if you undo it one more time, you'll see a, so let's duplicate this line, now run there, that's how we implement the moment pattern in this section I'm going to talk about. the state pattern let's say you want to create a drawing application like Photoshop in Photoshop and in many other applications we have a tool palette here and this canvas behaves differently depending on the tool we select, for example if you select the selection that We can see that the cursor icon changes now when we click and drag, we say this: rectangle similarly, if you select the brush tool and click and drag, we see this orange line, so basically this canvas object responds to mouse events like Mouse up and mouse. below, but what it does changes depending on the currently selected tool.
Let's simulate this in code, so in this project I will first add a new package state. We are going to write all the code for this section in this package. Now here we need a new class called canvas, this class should respond to mouse events like mouse down and mouse up, so here when the two methods are public override mouse down and I am going to duplicate this and rename from the second to mouse up now in both methods we must do it. different things depending on the currently selected tool the first minute to find out what is the currently selected tool we can represent that using an enum an enum in java is like a set of constants let me show you like this in this package we add a new class first we change the type of class to enum and then we call it tool type.
I heard we needdefine some constants as selection. Please note that I am using capital letters to name this constant. This is a convention in Java, so this is our selection tool. We also need a brush and an eraser now in our canvas class. Here we may need a field to store the currently selected tool, which is really easy, so the private tool type is current; we also need a getter and a setter for this field so we place the carrot here press alt' + enter' and create beautiful getter and setter now in our mouse down method we should write code like this if the current 2 is equal to tool type point selection here, we should change the cursor icon to the selection icon so that it simulates that by printing something on the terminal selection icon now, otherwise if the current tool is equal to the tool type tool of that brush, then we will print a different message brush icon once again, if the current total is equal to the tool type of that eraser, then we will print the eraser. icon now when is a similar code in the mouse method above so to save time I'm going to copy this and then paste it here and then change what we print in the terminal so that the moment the user releases the mouse button if the current tool is a selection tool you will draw a dashed rectangle, so draw a dashed rectangle, if the current tool is a brush we will draw a line and if it is an eraser we will erase something.
We could also implement this using a switch and a shifter. statement now, if you have been programming for a while, you have probably seen patterns like this in your code, you have a long list of LS or Sushant case statements and you have probably repeated these statements in different places in your code, so in In this example we have these decision making statements in these two methods, most likely in a real application in a real drawing application we should also respond to keyboard events like e up and key down and we probably have to repeat this whole making of decisions within those methods as well. so the approach we have taken is not maintainable, the more tools there are supported the longer these decision making statements will be and maintaining this code will be really difficult.
Also, here we have the lack of extensibility, it is not easy to extend this application. Let's say tomorrow we are going to add a new tool to draw a circle, we have to go to different parts of our code and make changes, for example in our mouse down method, we should add another else--if statement to see if the current The tool is the circle tool, then we change the icon to the circle icon, we have to make a similar change in the mouse up method, so extending this application is not easy now, what we really need here is to give the canvas the ability to behave differently depending on the currently selected tool, so in both methods we are running different code depending on the currently selected tool.
We want this method to behave differently depending on the current tool. In the course we talk about the four essential principles of object-oriented programming encapsulation abstraction. Inheritance and polymorphism Which of these principles do you think we can't play here to solve this problem? I want you to spend ten minutes on this exercise and figure out a way to solve this problem when you're done come back and watch the next lesson first. In the course we talked about polymorphism, I told you that polymorphism is a mechanism that allows an object to take on many different forms. , so earlier we built this UI control class and declared it abstract because it has a single abstract method.
Abstract methods are methods that we have no implementation, so here we have a drawing method, but we don't know how to draw a UI control, the drawing algorithm will depend on the type of UI control, so we create two specific UI controls , one of them was the textbox class, which extends the UI control and this is where we are implementing the logic to draw a textbox. Now in our main class we had code like this, we declared a static method called drawing UI control which takes a UI control and simply calls the control that draws that depending on the type of object we passed to this method , our application behaves differently, this is polymorphism in action, so if you have an instance of the textbox class, the draw method of the textbox class will be called even though we are working with the interface. user. control class here, so this control object can take many different forms, this is polymorphism, here is the UML diagram of these classes, so our main class communicates with the UI control, which is the parent or base of these two classes, textbox and checkbox in the UI control. we have an abstract method called draw and we have implemented this method in our child classes.
Now we can use the same technique to get rid of those ugly if and else statements in our canvas class, so here is our canvas class, we have the current tool field and these two methods we want these methods to behave differently depending of the current tool, so we introduce a new class called tool. This will be an abstract class like our UI control. In this class we will declare two abstract methods mouse up and mouse down what happens when the user releases the mouse button will be determined in the child classes so we introduce new classes like selection and brush.
In these classes we will implement the logic for mouse up and mouse down events, now our canvas class is going to work with the abstract tool class, it doesn't care about any specific tool, but it will behave differently depending on this specific tool that we provide to it at runtime and this is what we call a state pattern because the state pattern allows an object to behave differently. when the state changes now, if you look at the classic definition of the state pattern in the Gang of Four book or other course books, you will find different labels, so instead of canvas we have context and instead of tool we have state with two. concrete implementations too, instead of the mouse up and mouse down methods, we have the request method which is handled by the state class, so as I told you before, this is just an abstract concept, it doesn't mean that must name the context or state of its classes. two abstracts always use meaningful names that fit the domain of your application.
Below I will show you how to implement this state pattern in code.so here in state package let's add a new class tool in this class we need to abstract methods so that public summary override mouse down and mouse up now , because these methods are abstract we must also mark the class as abstract, now we could also use an interface here because an interface is simply a contract that determines the capabilities that a class should provide, so earlier you saw that metals in a interface don't have an implementation, they are exactly like our abstract methods here now, what is the difference between an interface and an abstract class, well they are both abstract concepts, we can't create instances of them, we can't create a new instance of this tool class or the tool interface, so since they are abstract and don't have much code, they allow us to build loosely coupled.
In applications we prefer to use an abstract class if you want to provide some common code to all child classes. In this case, we don't provide any common code to our tools, so I'll replace this abstract class with that interface. Check it out. public interface now in interfaces we don't need the abstract keyword because these methods are considered abstract by default so we remove the abstract keyword. Also, these methods are considered public, so we don't need the public keyword either, which makes our code cleaner. so we have an interface for a person take a tool now let's implement specific tools so let's add a class called selection tool here we write implements tool now note that here we have two interfaces with the same name the first one is the one that simply created, we also have a tool interface in the Java X package, don't worry about that, let's import the interface we created.
Okay now we need to implement this interface so we press alt' + enter' and implement these methods so this is where we implement the Logic with the selection tool when the user presses the mouse button we need to change the icon to the selection and when they release the mouse button, we should draw a dashed rectangle. Okay, now let's add one more class, this will be our brush tool. The Brush tool also implements the tool interface. Here we have a different logic so when the user presses the mouse button we should show the brush icon and when he releases the mouse button we should draw a line.
Now let's see how we can incorporate them into our canvas. class, so let's first open the canvas class, we need to change the type of this field from tool type to tool, so we are programming in an interface. Okay, now we have a bunch of compilation errors, it doesn't matter, let's delete them. all the code in these methods, all this nasty, disgusting code, now we should change the return type of our getter instead of the tool type, we will use tool and similarly for our setter, we will pass a nice tool object now in our mouse. below metaha we will call the current tool point mouse down and similarly here we call the current tool point mouse up that's all we have to do isn't this code beautiful?
So the canvas class is simply delegating for your specific tool to determine what should happen when the user processes or releases the mouse button with this implementation we don't have a long list of decision making statements so our application is more easy to maintain and we can also extend it easily, let me show you, for now we only have two types. of tools a selection tool and a brush tool, let's use this and then I'll show you how to extend this application to support a new tool, so let's go to our main class, first we create a canvas object, then Camus now sets the current tool . set the current tool here, we need to pass an object that implements the tool interface so we can pass a selection tool, then we call the mouse down and finally up, let's see what happens so that the icon changes to the selection icon and then let's draw a beautiful rectangle. if we pass in an instance of the Brush tool class we will get a different result.
There you have it, let's say tomorrow we'll support a new tool that's really easy. All we have to do is add a new class that implements the tool interface. look, here I'm going to add a new class, let's say eraser tool. You have this class that implements the tool interface and here we implement our logic, so delete your icon and here delete something. Now we go back to our main class and we simply pass in a new instance of the eraser tool class, take a look, we get a different result and that brings us to a very important principle in object-oriented programming, the open-closed principle which basically It means our classes should be open for extension but closed for modification, so we are not allowed to change the code in our classes, we can only extend it now with this principle, we can add new features without changing the existing code, we can support new features adding new classes now, why does this matter?
How many times have you met? changing the code in a class and then breaking something in your application, the opening and closing principle prevents situations like that. Every time we want to support a new feature, we simply add new classes and test those glasses, so following this principle makes our applications extensible and robust. If this concept is new to you, don't worry, you'll see more examples of this later in the course, so layout planners are great, they help us build maintainable, extensible and reusable objects; However, they are sometimes misused, here is an example. I have this guy here, his name is John Smith, he's a pretty arrogant developer, you've probably seen him in my othercourses.
He recently learned about design patterns and started refactoring some existing code to apply these patterns. She now feels superior to his co-workers. as a superstar developer just because you learned about this date pattern and applied it in the code, that's what I call pattern abuse, remember this, every pattern has a context, it's there to solve a particular problem and that's why I have taken a problem driven approach in this course so that you learn and understand when and how to apply these patterns, if you just blindly apply these patterns in your code you will increase complexity because you will end up with more moving parts so not only will you not will have solved the problem, but actually you created a new problem, you created what we call a design smell in your application, which is an application with an overly complicated design, some people call it over-engineered.
I don't like to use that term because a real engineer always tries. understand a problem first and then they think of several solutions and choose the one that best fits the problem, which is the definition of engineer, at least for me, designing a solution is what code monkeys do, programmers will blame the correct code without understanding the problem you are trying to solve as Leonardo da Vinci said simplicity is the ultimate sophistication so keep things simple and pragmatic, don't blindly apply these design patterns without understanding the problem you are trying to solve. Next, I will show you a real problem. example of state pattern abuse, okay, let me show you how the state pattern can be easily abused.
Let's say you want to implement a stopwatch application in this application. We need a stopwatch class with a click method, when we click on it it starts counting or stops, so in our state package let's add a subpackage. I'm going to call this abuse. Now to this package we are going to add a new class called stopwatch. Here we need the click now method, depending on the state of this object. do different things, we can represent the state with an enum with two states or we can use a boolean. I think a boolean is easier, so let's go with a boolean so that the private boolean runs now when we click the stopwatch, if it's running, then we're on.
We'll stop it, so we'll set it to be running to false and then print stopped; otherwise we will set running to true and then print running. Let's test our implementation after this point, so in the main class we create a stopwatch and then click on it initially. it stopped, so when we run this application we should see the running message. There you go, beautiful. Now if you click on it one more time, we see two messages running and then it stops. If we click on it one more time, we see that the operation has stopped working.
Beautiful, so this is a very simple and straightforward implementation now John Smith removes this code, he's sitting in the office and thinks hmm, the click method behaves differently depending on the state of the stopwatch, so that's the case of the state pattern, you will refactor this code like this First, you will create a new class or an interface called state, so we need an interface here. This interface will have a click method and it will have two classes that will implement this interface, so John adds two classes, one of them is stopped. state the other one is working state working state now both glasses should implement the state interface if the stopwatch is working we should stop it and then print a message, but how are we going to be able to stop this stopwatch that we don't have access to?
The stopwatch object here, well, we can add a constructor so that in the public running state we give this constructor a parameter of type stopwatch and then we store it in a field, so we declare a private field here. Private stopwatch, we call it stopwatch and initialize it in the constructor. this stopwatch is equal to stopwatch now in click method we need to change the state of stopwatch so first we need to go to stopwatch class and outside the field to store the current state of this object so that we are no longer in this field . declare a private field of type state called current state, now let's generate a getter and a setter for this field which is very easy here goes so let's go back to the running state when we call the click method we should change the state of the stopwatch , so We call that set state stopwatch and here we pass the next date which is the stopped state, so it is a new stopped state.
Now here we have a compile error because this class does not implement the state interface, so let's add the implementation state real quick. Back in the running State class, the problem is fixed, so we change the state and then print a message that says stopped. Now we need a similar approach in the stopped state class, so here we generate a constructor. I am going to show you a shortcut if you are on Mac press command + n if you are on Windows press ctrl + n with this we can open the generation palette and generate a constructor now here we can add a parameter which is stopwatch and at the same time we can create and initialize a private field, so we put the carrot on the parameter name, press alt' + enter' and select create field for the stopwatch parameter, there you have it, so we have a private field and this field is initialized here, beautiful now with the click method. should change the state of the stopwatch, so we call stopwatch, that is the current state, if it stopped, we need to set it to running state, so now we need to pass a reference to the stopwatch, which is the stopwatch field we have in this new execution state. class okay, so we print a message that says done, okay, now we have a compilation error and the state class running because when we try to change the state of the stopwatch we are passing a new instance of the stop state class, the constructor of the stop state. the class expects a stopwatch object, so we pass that object over here, problem, so it should indicate the classes and the final part goes to the stopwatch and replaces this implementation with the current state point click, so we are delegating the task of clicking the stopwatch to the state object and by the way, initially we should set it to the stopped state so that Neil stops the state.
Now here we need to pass a reference to a stopwatch object which will be this one that represents the current object that we have now finished in the main file. method, internally we change the stopwatch implementation but it behaves the same, let's run the program, we see exactly the same result as before, beautiful, however this implementation is much more complex than the simple if a nail statement we had before, so There is absolutely nothing wrong with even Sushant case statements or if you have some decision making branches in a single method, like we did in stopwatch class, we had those decision making statements in one place, no There is absolutely nothing wrong with that implementation, but in our example above in our canvas class we had those decision-making statements in multiple places in the mousedown and mouseover operation methods and, more importantly, if We wanted to support a new tool, we had to modify different parts of our code, that's the reason why we refactored this code, changed this structure and used this state pattern.
In contrast, in the stopwatch, all the decision making was in one place and we know that this Dulwich is not going to have a new state in the future, either stopping or running something that simple so that we don't have a maintenance problem here we don't have an extensibility problem we ended up refactoring this code well I didn't do it without problems but it made this code overly complicated without getting any benefit now that we have more moving parts we have an interface plus two implementations and our logic is distributed in these two different classes, in contrast to the previous implementation, all that logic was in one place, so here is the end result: Don't abuse design patterns, congratulations for completing this YouTube tutorial, as I told you before, This video is the first hour of my ultimate design patterns course.
If you want to learn more, I recommend that you sign up for my course where we talk about twenty other design patterns. These are the essential design patterns that every software engineer must master. The first 200 students can get the course at a huge discount, so if you are interested and will do it now, before this offer expires, you can find the link below for this video, thank you and have a fantastic day.

If you have any copyright issue, please Contact