تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Defining Algorithm Family0:49

down into bits and pieces. The first step, define a family of algorithms. So this means an algorithm or a task, more simply, that can be executed in multiple ways. So for our first demo, let's do something very simple. Maybe I need to log some bit of data. However, there are multiple strategies to execute this particular task. For example, we could log the value simply to a file, or we could log it to a database, or we could instead send some kind of cURL request up to a web service and view the data there. So really, there are multiple strategies to execute this single task. So why don't we represent that. And I'm going to use very readable class names here. For example, Log2File. And then maybe you'd have another one called Log2Database. And then that final example, Log2XWebService. These will represent our family of algorithms. Okay, fair enough. Let's move on to the next part of the definition. And I will paste that in here.

Creating Logger Interface1:44

final example, log2xwebservice. These will represent our family of algorithms. Okay, fair enough. Let's move on to the next part of the definition. And I will paste that in here. Encapsulate and make each one of these algorithms interchangeable. So think about this with me. How could we take any of these classes here and make them interchangeable? Do you have any ideas? Well, if you've gone through the SOLID series, then I bet you're thinking, hey, Jeff, we need to code to an interface. That's something we say here at Laracast all the time. And that's because this basic concept of depending upon abstractions rather than concretions is basically littered throughout our entire ecosystem. So to say it's the bedrock would be a massive understatement. Okay, so let's make this work. I'm going to create an interface here called Logger. And any implementation of that interface must offer a log method,

be a massive understatement. Okay, so let's make this work. I'm going to create an interface here called Logger. And any implementation of that interface must offer a log method, and it should pass through some data. That is our contract. So why don't we place this right here at the top? And now I will make these classes interchangeable by having them implement that contract. Implements Logger. And let me just duplicate this. Okay, so this first one, when we log, we'll accept some data. And like we always do, I want the code to be very light. So we will var_dump, log the data to a file. Okay, now for this next implementation. And keep in mind, presumably, there would be a lot more involved here. But anyways, log the data to the database. And then finally, our third option would be to post the data up to some special online service, we'll just say log the data to a SaaS. Alright, so I feel pretty good.

Naive Usage and Coupling3:28

log the data to the database. And then finally, our third option would be to post the data up to some special online service, we'll just say log the data to a SaaS. Alright, so I feel pretty good about this, we've tackled the two important parts of that definition, we create a family of algorithms, and then we allow them to be interchangeable at runtime by coding to an interface. Now let's review some usage. And forgive me, I'm putting it all within one file, just to make it a lot easier to consume for the lesson. So maybe you have some kind of App class, or whatever you want your context to be, I'm just going to add a helper method here called log. And then this would be responsible for deferring to or referencing one of these algorithms, quote unquote. Now in the past, you might just new up one of these classes on your own. So maybe initially, you just want to log to a file. So you would say something like $logger = new LogToFile. And then you would say

you might just new up one of these classes on your own. So maybe initially, you just want to log to a file. So you would say something like $logger equals new LogToFile(). And then you would say $logger log and pass through the data. So let's see what that might look like. Create our app somewhere. And then when I need to log some data, we say log some information here. Okay, let's run that from the terminal and see what we get. php index. And there we go, it seems to be working. But now maybe we decide that under certain circumstances, we actually want to log to a database or log to this SAS service or something like that. But the problem is because we've hard coded this, we have now tightly coupled our application class to a specific logger. And as a result, we have no easy way to swap this out. And this is exactly where both the strategy pattern, as well as polymorphism in general, come into play. Let's see what that looks like. Now I'm no

Injecting Strategy at Runtime5:15

a result, we have no easy way to swap this out. And this is exactly where both the strategy pattern, as well as polymorphism in general, come into play. Let's see what that looks like. Now I'm no longer going to hard code that in, I'm simply going to say not a LogToFile object, but instead, just some algorithm that adheres to the Logger interface. So now we accept the logger. And we could pass that in right here, new LogToXWebService. So if we run it this time, now we're logging the data in a totally different way than we did it before. But if we ever need to swap this out at runtime, then I can update this. Now we're going to log to a Database, we run it, and now it's working. So once again, to reiterate, this is specifically what the strategy design pattern allows for. You create a set of algorithms, think of it as multiple ways to execute a particular strategy. Then we force them to be interchangeable within our app by making them adhere to a common

allows for. You create a set of algorithms, think of it as multiple ways to execute a particular strategy. Then we force them to be interchangeable within our app by making them adhere to a common interface. Finally, within your context class, you simply specify that you need to use some kind of logger. And really, if you think about it, this class doesn't really need to care about how you go about doing it. It just needs to know that you can do it. And by the way, if you want, you could even set a default. So what some people will do is maybe say, if you passed in a logger, then of course use that. Otherwise, here, we will default to something specific, like log to file. Now, if I don't pass anything, we will log to a file when using that app class. But if I need something more specific, then I can pass that through. And now I've swapped out how we execute that task at runtime. So now that we've reviewed a basic example, like we always do, I want to show you where this might

Laravel Mail Drivers Example7:04

specific, then I can pass that through. And now I've swapped out how we execute that task at runtime. So now that we've reviewed a basic example, like we always do, I want to show you where this might exist in the real world. And let's use the Laravel source in this example. As you know, in Laravel 5, we have a mail driver. And if we take a look at our mail configuration, you'll see what I mean. We could use SMTP, we could just log the mail and not actually send it, or we could use something like Mailgun or Mandrill. And all we have to do is set the driver here, and behind the scenes, magically everything will just work. It's one of the cool things about Laravel. However, what you may not know is that the strategy pattern is being used here. Let me show you what I mean. If we switch over to Laravel's MailServiceProvider and scroll down, don't worry about most of this stuff. But right here, where we register the Swift transport, notice that we

If we switch over to Laravel's mail service provider and scroll down, don't worry about most of this stuff. But right here, where we register the Swift transport, notice that we return a new transport manager. And if we then take a look at that, this basically contains some factories, another design pattern, where we just build up an object. So for example, if we want to use SMTP, then we grab some information from the config, we build up an object, and then ultimately that's what we return. If we want to take a look at another one, how about Mailgun? Well, it grabs our Mailgun settings from that configuration file, and then it builds up this MailgunTransport class. But if I scroll down to Mandrill, a different service, well, that's basically returning a MandrillTransport. So these seem a little similar. I'm starting to get the idea that we can swap these in and out. Let's take a look. MailgunTransport. And here we go. So this is

Comparing Transport Implementations8:46

Mandrill transport. So these seem a little similar. I'm starting to get the idea that we can swap these in and out. Let's take a look. Mailgun transport. And here we go. So this is one algorithm. And if we go to Mandrill transport, there's another algorithm, so to speak. And notice that we have them both implement the same contract. And going back to our definition, where you encapsulate each one and make them interchangeable, that very thing is at play right here. So let's see. We have a send method here, and this is how we handle the process of sending mail using Mandrill. We send a POST request to this URL and pass through the body. Cool. But now, if we want to swap that out and use Mailgun, well, we scroll down to the send method, and now that sends a slightly different request. But we also have other things. Let's take a look. How about the log transport? So if this is where we don't actually want to send the mail but we just want to log it,

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟