the adapter pattern in php

25
THE ADAPTER PATTERN DARREN CRAIG @minusdarren

Upload: darren-craig

Post on 06-Aug-2015

94 views

Category:

Software


0 download

TRANSCRIPT

Page 1: The Adapter Pattern in PHP

THE ADAPTER PATTERN

DARREN CRAIG@minusdarren

Page 2: The Adapter Pattern in PHP

S.O.L.I.D. OOP

★ Single Responsibility ★ Open / Closed ★ Liskov Substitution Principle ★ Interface Segregation Principle ★ Dependency Inversion Principle

Page 3: The Adapter Pattern in PHP

LISKOV SUBSTITUTION PRINCIPLE

“objects in a program should be replaceable with instances of their subtypes without

altering the correctness of that program.”

Page 4: The Adapter Pattern in PHP

THE PROBLEM

“Allow users in our system to post updates to Facebook.”

- The Client

Page 5: The Adapter Pattern in PHP

WE MEET THEIR REQUIREMENTS

class User

{

public function updateStatus($status)

{

$facebook = new Facebook\Facebook;

$facebook->updateStatus($status);

}

}

// The Facebook SDK

class Facebook

{

public function updateStatus($status);

}

$user->updateStatus($status);

Page 6: The Adapter Pattern in PHP

NEXT…

“Allow users in our system to post updates to Facebook or Twitter”

- The Indecisive Client

Page 7: The Adapter Pattern in PHP

WE MEET THEIR REQUIREMENTS

class User{

public function updateStatus($status, $gateway = 'FACEBOOK') {switch($gateway) {

case: "FACEBOOK";$facebook = new Facebook\Facebook;$facebook->updateStatus($status);break;

case: "TWITTER";$twitter = new Twitter\Twitter;$twitter->postStatus($status);break;

}}

}

// The Twitter SDKclass Twitter {

public function postStatus($status);}

$user->updateStatus($status);

Page 8: The Adapter Pattern in PHP

“We’re changing the updateStatus()

method to createStatus()”

NEXT…

Page 9: The Adapter Pattern in PHP

“We’re changing the updateStatus()

method to createStatus()”

NEXT…

Page 10: The Adapter Pattern in PHP

FINE…

class User{

public function updateStatus($status, $gateway = 'FACEBOOK') {switch($gateway) {

case: "FACEBOOK";$facebook = new Facebook\Facebook;$facebook->updateStatus($status);break;

case: "TWITTER";$twitter = new Twitter\Twitter;$twitter->postStatus($status);break;

}}

}

Page 11: The Adapter Pattern in PHP

FINE…

class User{

public function updateStatus($status, $gateway = 'FACEBOOK') {switch($gateway) {

case: "FACEBOOK";$facebook = new Facebook\Facebook;$facebook->updateStatus($status);break;

case: "TWITTER";$twitter = new Twitter\Twitter;$twitter->postStatus($status);break;

}}

}

class User{

public function updateStatus($status, $gateway = 'FACEBOOK') {switch($gateway) {

case: "FACEBOOK";$facebook = new Facebook\Facebook;$facebook->createStatus($status);break;

case: "TWITTER";$twitter = new Twitter\Twitter;$twitter->postStatus($status);break;

}}

}

Page 12: The Adapter Pattern in PHP

BUT…

class HufflepuffController {

public function updateStatus($status, $gateway = 'FACEBOOK') {

switch($gateway) {

case: "FACEBOOK";

$facebook = new Facebook\Facebook;

$facebook->updateStatus($status);

break;

case: "TWITTER";

$twitter = new Twitter\Twitter;

$twitter->postStatus($status);

break;

}

}

}

Page 13: The Adapter Pattern in PHP

BUT…

class HufflepuffController {

public function updateStatus($status, $gateway = 'FACEBOOK') {

switch($gateway) {

case: "FACEBOOK";

$facebook = new Facebook\Facebook;

$facebook->updateStatus($status);

break;

case: "TWITTER";

$twitter = new Twitter\Twitter;

$twitter->postStatus($status);

break;

}

}

}

class GryffindoorController {

public function updateStatus($status, $gateway = 'FACEBOOK') {

switch($gateway) {

case: "FACEBOOK";

$facebook = new Facebook\Facebook;

$facebook->updateStatus($status);

break;

case: "TWITTER";

$twitter = new Twitter\Twitter;

$twitter->postStatus($status);

break;

}

}

}

Page 14: The Adapter Pattern in PHP

BUT…

class HufflepuffController {

public function updateStatus($status, $gateway = 'FACEBOOK') {

switch($gateway) {

case: "FACEBOOK";

$facebook = new Facebook\Facebook;

$facebook->updateStatus($status);

break;

case: "TWITTER";

$twitter = new Twitter\Twitter;

$twitter->postStatus($status);

break;

}

}

}

class GryffindoorController {

public function updateStatus($status, $gateway = 'FACEBOOK') {

switch($gateway) {

case: "FACEBOOK";

$facebook = new Facebook\Facebook;

$facebook->updateStatus($status);

break;

case: "TWITTER";

$twitter = new Twitter\Twitter;

$twitter->postStatus($status);

break;

}

}

}

class HogwartsController {

public function updateStatus($status, $gateway = 'FACEBOOK') {

switch($gateway) {

case: "FACEBOOK";

$facebook = new Facebook\Facebook;

$facebook->updateStatus($status);

break;

case: "TWITTER";

$twitter = new Twitter\Twitter;

$twitter->postStatus($status);

break;

}

}

}

Page 15: The Adapter Pattern in PHP
Page 16: The Adapter Pattern in PHP

IT’S A PAIN

★ We should be able to easily add new gateways whenever the client asks

★ We should be able to easily adapt to API changes without too much trouble.

Page 17: The Adapter Pattern in PHP

ADAPTERS FTW!

★ We need an interface that defines the functionality required by out application

interface UpdatesStatuses

{

public function post($status);

public function delete($statusId);

}

Page 18: The Adapter Pattern in PHP

FACEBOOK ADAPTER

class FacebookAdapter implements UpdatesStatuses

{

private $facebook;

public function __construct(\Facebook\Facebook $facebook)

{

$this->facebook = $facebook;

}

public function post($status)

{

$this->facebook->createStatus($status);

}

public function delete($statusId)

{

$this->facebook->deleteStatus($statusId);

}

}

Page 19: The Adapter Pattern in PHP

TWITTER ADAPTER

class TwitterAdapter implements UpdatesStatuses

{

private $twitter;

public function __construct(\Twitter\Twitter $twitter)

{

$this->twitter = $twitter;

}

public function post($status)

{

$this->twitter->postStatus(status);

}

public function delete($statusId)

{

$this->twitter->removeStatus($statusId);

}

}

Page 20: The Adapter Pattern in PHP

TAKING IT FURTHER

★ We want users to be able to add several social accounts (connected accounts)

★ When they post using our application, the post should also be shared on all of their social accounts.

Page 21: The Adapter Pattern in PHP

SOCIAL ACCOUNTS INTERFACE

interface SocialAccount

{

public function connect();

public function post($post);

// other stuff

}

Page 22: The Adapter Pattern in PHP

SOCIAL ACCOUNT CLASSES

class FacebookAccount implements SocialAccount{

public function __construct(Facebook\Facebook $facebook) {$this->facebook = $facebook;

}

public function post($post) {$this->facebook->createPost($post);

}}

class TwitterAccount implements SocialAccount{

public function __construct(Twitter\Twitter $twitter) {$this->twitter = $twitter;

}

public function post($post) {$this->twitter->makePost($post);

}}

class LinkedInAccount implements SocialAccount{

public function __construct(LinkedIn\LinkedIn $linkedin) {$this->linkedin = $linkedin;

}

public function post($post) {$this->linkedin->makePost($post);

}}

Page 23: The Adapter Pattern in PHP

THE USER

class User{

private $connectedAccounts = [];

public function addConnectedAccount(SocialAccount $account){

$this->connectedAccounts[] = $account; }

public function postToAccounts($status){

foreach($this->connectedAccounts as $account){

$account->post($status);}

}}

$user->addConnectedAccount(new FacebookAccount(new Facebook\Facebook));$user->addConnectedAccount(new TwitterAccount(new Twitter\Twitter));$user->addConnectedAccount(new LinkedInAccount(new LinkedIn\LinkedIn));

// Sometime in the future.$user->postToAccounts($status)

Page 24: The Adapter Pattern in PHP

PRO TIP: IOC - INVERSION OF CONTROL

★ Resolves classes and their dependencies without having to institute them each time

$user->addConnectedAccount(new FacebookAccount(new Facebook\Facebook));

// becomes

$user->addConnectedAccount(new FacebookAccount());

★ Laravel has a built in IoC container ★ A few platform agnostic packages available (Pimple, Dice)

Page 25: The Adapter Pattern in PHP

QUESTIONS?