Next lesson playing in 5 seconds

  • Overview
  • Transcript

3.1 Adapter

The aptly named adapter pattern is just that: an adapter between different APIs or codebases. In this lesson, you'll learn how to implement the adapter in order to work with incompatible interfaces.

1 lesson, 01:40


2.Creational Patterns
2 lessons, 11:52



3.Structural Patterns
4 lessons, 33:47





4.Behavior Patterns
4 lessons, 36:32

Chain of Responsibility




1 lesson, 01:06


3.1 Adapter

The adapter pattern is one of those that we don't really need to define, because it is aptly named. We essentially write a software adapter so that we can use two incompatible APIs. So let's say we are writing a website that allows users to make payments. And the current thing to do is to use a company called FooPay. Now this FooPay class is not one that we would write, this is coming from a library written by the people at FooPay that they are making available to us. And this FooPay class has a method called makePayment. We pass in the amount of money that we want to pay, and then of course, the payment is made. But this method is just going to say that this is FooPay, this is the amount, voila. So as far as our code is concerned, we would create our $gateway object. So we would new up FooPay, and then we would use our $gateway's makePayment method to make a payment. So we're going to make a payment of 100 of whatever currency that is, and we will run this, and there we see FooPay: 100. So that's great, but a couple of years later, there's a new company called BarPayments. And the early adopters want to use that, and that's enough people that we really need to implement this. So we look at BarPayments, they have a library that we can use within our application. So this is the class that would be in that library. So we would have this BarPayments class, it would have a method [LAUGH] called releaseFunds, isn't that wonderful? So it's completely different than what we have for our FooPay. So as far as our code is concerned, we're going to have to do some refactoring in order to fit in the BarPayments system. But that is where the adapter pattern comes into play. And the first thing we're going to do is write an interface, because we will essentially have two different adapters. We will have a FooPay adapter and then a BarPayments adapter. So we're going to define our own interface that is going to allow us to consolidate all of our payment gateways under a unified API. So this is going to have a method called pay. We're going to pass in the amount, and then our different adapters are going to use the different APIs. So we have FooPay and BarPayments, we're going to have a FooPayAdaptor that implements the IPaymentAdapter. And inside of this class we need a reference to our FooPay object. So we're going to have a private $fooPay, and we're going to have a constructor where we're going to pass in our FooPay object. Now you might ask, why would we still create that object? Why don't we let the adapter create that object for us? And the answer is dependency injection. So we are going to set our fooPay property to the value passed to the constructor. And since this implements the IPayment adapter, we need to implement the pay method. And inside of this pay method we are going to use our fooPay object's makePayment method. And so, once we finish with this, we will create an adapter for our BarPayments. And really, what we are going to do is copy what we just wrote, and then paste it in, and make the necessary changes. So this is no longer a FooPay adapter, this is a BarPayments adapter. And we will just copy that, we'll change FooPay there, we will change our name to $barPayments. And then we will make the necessary changes there. And so that inside of the pay method, we are going to use the releaseFunds method to make our payment. And so now our client code is no longer like this. What we would do is we would still have our gateway, but we would new up our adapter. So if this was for a FooPayment, we would say FooPaymentAdapter. We would then pass in a new FooPay object, and then we would say $gateway, we would use the pay method, and then the $amount. And then let's go ahead and create a BarPaymentsAdapter as well. And the we will use that to make a payment. So BarPayments, and so inside of our command line we should see, well we see a fatal error, FooPaymentAdapter is not found. Why is that? FooPay, that's why. It helps if you name things correctly, so let's go back, let's run it. And now we have an undefined on 42. So we have $amount, that is of course wrong, so we paid 100 and then for BarPayments,we make 200. So now we see that it works. We have FooPayment 100, BarPayments 200. So now the idea is this. We, of course, are going to be loading the user's profile information. So what we could do is, of course, through the configuration they go in and set we want to use FooPay or we went to use BarPayments. And so then would then have $user, we can have a property called paymentProvider, which would be pointing to one of these adapters, so that then all we have to do is use pay. We pass in the amount that they want to pay, and then we're good to go. And if they decide to change, to use another payment provider, well we don't have to change our code at all. The payment provider that they choose is going to be referenced with this payment provider. And since we have adapted our API, we still use our pay method. Now there's another benefit to using the adapter pattern. Let's say that FooPay updates their API so that they no longer have a makePayment method, they have simply a pay method. So now that we are using the adapter pattern, all we have to do is go to our FooPay adapter, and then change the method that we use inside of our pay method. It makes our code easier to maintain because we have abstracted out all of the, I'm going to say, volatile API. And I say volatile because we don't control it, it is provided by FooPay. FooPay can change their API at any time, so therefore, it's volatile. And by using the adapter pattern, we've made our code more resilient to that volatility. So the adapter pattern is very much like a hardware adapter, it allows us to adapt incompatible APIs.

Back to the top