- Overview
- Transcript
2.4 Prototype
The prototype pattern is a way to implement object cloning. Using the prototype pattern, we are able to create new instances of a class simply by creating a point-in-time copy, or clone, of an existing instance of that class.
1.Introduction2 lessons, 04:27
1.1Introduction01:39
1.2Prerequisites02:48
2.Creational Patterns5 lessons, 52:47
2.1Factory10:16
2.2Abstract Factory12:24
2.3Singleton09:09
2.4Prototype09:18
2.5Builder11:40
3.Structural Patterns7 lessons, 1:05:54
3.1Adapter10:07
3.2Flyweight10:33
3.3Proxy05:53
3.4Bridge10:35
3.5Decorator11:44
3.6Composite09:43
3.7Facade07:19
4.Behavioral Patterns9 lessons, 1:25:42
4.1Iterator09:32
4.2Command07:48
4.3Chain of Responsibility13:47
4.4Mediator08:16
4.5Memento08:53
4.6Interpreter14:31
4.7Observer08:58
4.8Strategy07:36
4.9State06:21
5.Conclusion1 lesson, 02:42
5.1Conclusion02:42
2.4 Prototype
The next design pattern that I wanna spent a little bit of time working on is what's known as the prototype pattern. Now, the prototype pattern is basically this, let's say that over the lifespan of a particular object or instance of a class. I want to be able to create copies, or clone that particular object at any point in time and get its current state. Now, why is this interesting? Well, it's interesting because at any point in the lifecycle of an object, I don't want to have to create a brand new instance of that class. And then copy over all of the current state properties or what have you of that object into another one. I'd much rather just be able to look into that object and say, hey give me the current state. Or clone this particular object so that I get a copy and it's all kind of self-contained. So let's see what something like that might look like in the world of Swift. So let's go ahead and create the prototype pattern playground. And this is once again going to be creational, so we'll hit Create. And now within here, I can start to play around a little bit. So let's say, an interesting situation where I might need something like this would be, let's say I'm dealing with some sort of sport. Let's say I'm creating an application that is tracking the current score or the statistics for a particular game or a sport or what have you. As a simple example I'm going to use basketball, but you could use any sort of sport or any sort of other kind of idea that you might want. So let's say that I have a class called BasketballGame. And within BasketballGame I am able to do a number of different things that have a number of different properties that I have to keep track of. But let's kind of keep things simplistic for now. Let's say that I have a quarter, so each BasketballGame is divided into four quarters. And this is going to be an integer and by default it is going to be the first quarter. So every time I create a new game it is going to be the first quarter. Then the home team is gonna have the score. Once again it's gonna be an integer, it's gonna be zero. And the awayScore is also going to be an integer and it's gonna be zero. So as you can see, every time now that I create a new instance of this BasketballGame, it's gonna have these properties. And they're all gonna be initialized to their defaults. So 1, 0, and 0, which is okay when I'm creating a new instance of this game. But not what I want to get a copy or for whatever reason, get a clone of this object. I don't want those defaults, I want whatever the current state is. So how can I do something like that? Well, just to make things a little bit more interesting, let's go ahead and create a couple functions in here. Just so that we have an easy way to get in here and modify things a little bit. So let's say we have a function, this is gonna be called incrementHomeScore. So within here we can increment the home score and we can specify the number of points as an integer that we want to increment the home score as. So we can say homeScore + = points. And let's do the same thing for the awayScore. So let's go ahead and copy this, we'll paste it down here. And we'll say that this is going to be the awayScore just like that. So go ahead and save that. And then also, periodically throughout the game, as time goes on we may want to increment the quarter, or advance e quarter or something like that. So once we've done that, now we are simply going to say if the quarters, since there's only four quarters, if the quarters < 4, then we can go ahead and say, quarter + 1. So we can advance the quarter, or increment the quarter, or whatever have you. Okay, so now we have this, but what I wanna be able to do throughout the course of the game is I want to able to create clones of this. Because let's say I want to, at the end of the first quarter, I wanna get the first quarter statistics, what the score was, and anything else that I'm tracking. And then I have that kind of clone of that point in time copy of my BasketballGame object. And then I can keep using the original one to advance throughout the status of the game as it goes on. So, I might wanna take snapshots periodically throughout the game, for whatever reason. So that I can display it to the person watching it on TV or on some sort of feed that they're watching over the internet, or something like that. But I wanna be able to get periodic clones throughout the life cycle of this game. So how do we do that? Well, traditionally, there's a couple of different ways. Traditionally, you would probably see something within the class in the form of a function called clone. Now a clone would typically not take in any parameters, but it would return an instance of the object that we're currently in, in this case, of a basketball game. So what would we wanna do here? Well, we'd wanna return something, but usually in order to facilitate this, what we would wind up doing is providing some sort of initialization or a constructor. So let's take a look at that as well so we can say init. And then within here we'd say, well all right well we could initialize a quarter, which is gonna be an integer. We could initialize the homeScore, which is once again gonna be an integer. And we could initialize the awayScore, which is also going to be an integer. And we would, in this case, just initialize all of our properties. So that self.quarter would be equal to quarter. self.homeScore would be equal to homeScore. And then finally, self.awayScore would be equal to awayScore, just like that. So now we have this way to initialize if we should so choose. But we may not necessarily want to provide the initial values, we may just wanna go by the default values. And in that case, we could provide an empty initialization function as well, to say, if I don't wanna pass anything in that's okay too. I could just go by the defaults. So now at this point, the clone function is going to return a new instance of the BasketballGame. That's going to be the same current state as the version that I'm dealing with right now or that I'm within. So I could simply say return BasketballGame, and then I want to specify all of my parameters. So I would say self.quarter, self.homeScore, and self.awayScore. So now the result of my clone function is going to be returning a new instance of BasketballGame. But it's initializing it with the current state of whatever this particular object already is. So let's see what something like that might look like. So I could say let game = BasketballGame. And I don't wanna specify any of the parameters. I just wanna go with the defaults and then the game goes on. So after a period of time we're doing a bunch of incrementation, so I could say incrementAwayScore by 25. And then I could say game.incrementHomeScore by 22. And at this point, I've now created a new game, I've incremented the score a couple of times. And at this point, if I wanted to take a snapshot of my game, I could say let firstQueryStats = game.clone. So at this point now, I could say in the first quarter stats, what was the homeScore, and I could also say, what was the awayScore. So at that particular point in time I know the current score was 25 to 22. So at this point now, the game would have incremented the quarter so now I'm going to be in the second quarter. And let's say I did something similar, the game kept going on. And let's say that it just did the other way, so we just did 22 and 25 and now I can take another snapshot. I could say let secondQueryStats = game.clone. And at this point now I could do something similar to what I did before, if I wanted to get the current statistics from the second quarter. But in this case, I'm saying secondQueryStats, just like that. So now, after I increment all of these things, you now see that after the second quarter, my score is at 47, 47. So now I have used the prototype pattern to inject some functionality within my BasketballGame class to allow clones to be made off the current state of that particular object. So that I could get a clone and do whatever I want with that without affecting the current state or the current status of whatever my original object is for that particular class.







