 Hi, welcome to Visual Studio Toolbox. I'm your host Robert Green, and with me is Phil Jepixi. Hey, Robert. Hey, Phil. How are you? Good. Good. We're going to talk about another pattern today. We are going to talk about another pattern today. And we're going to talk about the strategy pattern. We are. Cool. All right, so what is the strategy pattern? The strategy pattern, well, according to Wikipedia, is a behavioral. Now, that's what we focused on the last two patterns we talked about were behavior as well. So we're going to cover the behavioral first, and then we'll do struct rule and creational. But it's a design pattern that enables, I should point here, where our viewers can see, that enables an algorithm's behavior to be selected at runtime. Now, this is different than just having different options. Let's go back to your weather example. Yes. If I had in the button click, if I could choose between get detailed weather, get weather, get 15-day forecast, those are different methods. Yes. And by calling a different method on that, I'm not changing the weather service's behavior. Right. I'm just using different parts of the API. That's not really a pattern, right? But if I just had a get weather method, and based on some condition, it would return detailed one-day, 15-day different types of weather forecast. Based on the last one you called, there is an option to change, whether you want simple detailed or forecast, for example. But when you just call get weather, it says, OK, what did you ask for last time? Last time you asked for the 15-day forecast, this time I'm going to give you the 15-day forecast. Or last time you asked for detailed, I'm going to give you the detail this time, but it's always still a get weather method. Right. That's a strategy pattern. Yeah. And to be clear, the tracking what you did last time and doing that same thing again is not the strategy pattern. The part of the strategy pattern is that I can get these different behaviors at runtime. By calling the same method. By calling the same method, right? So the tracking what you did last time is outside the strategy pattern, right? I just want to make that distinction clear. OK. Another good example is log for net. So log for net, I set it up. It's logging at a certain level, probably only errors and maybe critical. And then something's going on in the server. I need more information. I change the configuration. And now the behavior changes at runtime and spits out a lot more information. OK. For the viewers at home, if you start searching for examples of this, everybody's going to show a custom sorter. So I have a sort interface. I might do a bubble sort. I might do, I don't remember what all sorts. It's been a long time since I'd CS101. But some sorts are quicker based on the number of records. And so if you have a small number of records, then the class will decide, hey, I'm actually going to do this type of sort. If I find out that I have more than a certain number of records, I change my behavior at runtime and use other type of sorts. OK. Right? So it's dynamically changing behavior. But it's still just calling sort. We're still just calling get weather. Right? So if you watched our solid design patterns talk that we did, you'll recognize this code. We have an interface that's iHero. And I'm probably going to say this in every one of these episodes, when I do demonstration code, I never use a real domain. Because then people who are experts in that domain get hung up on the details of the implementation. I didn't know I don't have any superheroes watching this episode. I'm sure everybody who's out there developing is a code superhero. But here is my thing that will change. And it's doHero stuff. So this is log, get weather, set price. We didn't talk about that example we did in prep for this show. Let's say I've got an e-commerce solution. And we've got a power outage at our cheese warehouse. And we've got to unload this cheese, because there's nothing worse than rotting cheese. So we want to change the price of cheese, but only while the power is out. Well, if we didn't have some way of changing behavior at runtime, then we would have to do a new deploy to promote the cheese. And then when the power came back on, we'd have to redeploy code again to change it. Now, that's stretching the strategy pattern definition a little bit, because really what we should be doing is having those prices in a database and pulling a different value out of the database for price isn't truly the strategy pattern. That's just changing in attributes. But if we had some promotion, if you buy one, you get three free or something like that. And it changes. And again, we'll keep using this e-commerce thing. Take order, charge customer, pick, pack, and ship. But dynamic pricing would use the strategy pattern, because the algorithm you use to generate the price could vary based on time of day, percentage of seats already sold, et cetera. That would be using the strategy pattern. Because there's going to be a get price method, and again, using the command pattern, get price method, and then what algorithms that runs, which is A, none of my concern, because I'm just calling get price, and then B is going to be based on algorithms in various conditions. That's the strategy pattern. OK. So really, we're just changing behavior at runtime. And that's a very broad definition. And as we've said on each of the shows, it's a design pattern. It is just a basic example. We've done this thing before. Here's how we would do it. And pseudo code, if you will, and implementation details are up to you. So here's my do the command. Here's my change what it does. So this is the simplest level. If we look at the different superpowers that our heroes can have, a regular Joe doesn't have any. Notice that I'm always coding to an interface. This is key in this point, because I need to be able to pass in a specific implementation but not be locked into a specific implementation. So I have fly, I have fight, and I have weave a web. So my different hero classes get constructed with a default power. I then exercise that power. And it is, I don't know what the power is because it's an interface. And then I can change the power. So if we look at Spider-Man by default, Spidey weaves a web. Superman flies, Batman fights. So using this, I was about to say in real life, but I guess that's a little ironic to say. I've got Spider-Man is here. He weaves a web. We make sure that that's what he actually does. Now I could have used mox as well to prove that the methods were called. I have Superman who flies, Batman who fights. But that doesn't show the strategy in action. This next one does here. And I just have a node in there. I didn't want to over complicate this example. But this is a good spot for an inversion of control container, like Unity or NINJECT or any of those. Because what I want to be able to do is not have to hard code this stuff at design time but have a completely dynamic based on this dependency inversion. But I have Spider-Man, weaves webs. He runs out of web slinger juice. And he has to change his power. Now he's just fighting. He's not spinning webs. And then he needs to change it again because he is losing the battle. And he has to go rescue Mary Jane. So he uses, he gets a new web cartridge, shoots a new building, and flies away. So same superhero, but we've changed his behavior at runtime. But in all three cases, you're just calling doHero stuff. And the calling code is not on the hook for understanding what that means. So since she's calling a command, go do your thing. And the strategy pattern enables us to change that command at runtime. So let's take it back to the remote control example that we used in the command pattern talk. So I've got my remote control and I've got a button that says VCR, sorry, DVR, and I push that and it turns on to DVR. Well, with the strategy pattern, you could have fun with your neighbor because then you could at runtime change which buttons do what, right? So now I push the DVR button and instead of turning on the DVR, maybe it starts a copy maker. Or you could have a remote control that's smart enough to know that you've got new equipment and then it adjusts itself based. Wouldn't that be awesome? That would be even better than messing with your neighbor. All right, cool. And then the way you implement this, whether you're using IOC, you're just hard coding it here is independent of the fact that you're using a particular pattern, right? Correct. Again, getting back to the original, the door pattern, right? The door pattern says you need a way of moving from room to room that can be closed. Right. Whether you have a moving walkway that takes you to the door and then the door magically disappears and then the moving walkway continues and the door closes or you go and you have to actually manually pull a handle or you've got a remote that opens it. Or it's voice activated. Or it's voice activated or whatever is an implementation detail. Doesn't change the fact that you're using a particular pattern. Correct. And I think this is, we'll probably wind up coming back to this point over and over again. So if it starts to get old in future episodes I apologize ahead of time. But I think it's really important to understand because sometimes when we talk about new concepts like design patterns and we discuss this with a test driven development, there's the basics of what it is and then there's the implementation that the person's showing you and it's not always clear that you can use a pattern or do a particular or do test driven development without all of the rest of it. Right. So I just wanna make that clear that the fact that you can call do hero stuff three times and what that means changes is the usage of the strategy pattern. Correct. And then how you implement it is just how you wrote the code. Right. Okay, cool. And this is again just a simple example but the key here, we've been harping I've been harping on this since we did the first solid talk that we broadcast you have to be programming to an interface. Right. If in my Spider-Man hero, right, I'm assigning a weave web power here but if I overrode the do hero stuff to always execute weave web. Right. And I had to change because his web slinger ran out of juice I can't do that. Right. He'd have to say time out. Mm-hmm. You gotta stay here. I'm running back to my aunt's house. Right. I'm gonna get a new web juice and come back and it will unfreeze. Right. Well, it doesn't happen that way, right? The bad guys will be gone. Right. Your customers will be gone. Right. And then as you're building this you know that there is a requirement for this superhero object to be able to do different things based upon conditions. So now you think to yourself, ah, I'm going to use the strategy pattern to implement that. Yes. And then that lets you know that you're gonna call the same method three different times and now you ask yourself, okay, how am I gonna make that method do different things three different times? That's the implementation. That's kind of the order that you think about it, right? You don't write a bunch of code and then say, oh, I think I'll use a pattern here. You kind of think about it up front and then implement it. Yeah, and the thing to be careful about that happens to all of us is usually everybody's favorite pattern is the one they just learned. Mm-hmm. So it's, oh, hey, this strategy pattern. I'm gonna use it here. Right. It's not, that shouldn't be the thought process. The thought process is exactly what you said. I've got a toolbox. I've got hammers. I've got screwdrivers. I've got mallets. I've got saws. I've got all these different things. And what's the problem in front of me? Yeah. Oh, I need to have an opening cut somewhere. Well, could you do it with a hammer? Yes, you could probably knock down an opening in the wall with a hammer, but it's gonna be really ugly. Yeah. Cool. All right. All right. That's a strategy pattern. That's a strategy pattern. All right.