Skip to content

Instantly share code, notes, and snippets.

@jamiehannaford
Last active August 29, 2015 14:02
Show Gist options
  • Save jamiehannaford/207c011a3cc45ff70e24 to your computer and use it in GitHub Desktop.
Save jamiehannaford/207c011a3cc45ff70e24 to your computer and use it in GitHub Desktop.
<?php
/**
* This is our contract
*/
interface Service
{
public function doSomething();
public function doSomethingElse();
}
/**
* This is one of our SDK classes
*/
class ComplicatedService implements ServiceInterface
{
public function doSomething()
{
// custom logic
}
public function doSomethingElse()
{
// more custom logic
}
}
/**
* If a consumer wants functionality from one of our classes,
* extending it brings lots of inflexibility because it binds
* you statically to the implementation of the parent. You get
* everything in the class, which is often not what you want.
*/
class App extends ComplicatedService
{
public function doSomething()
{
return 'Some custom message ' . parent::doSomething();
}
public function doSomethingElse()
{
// I didn't even want this parent method! Do I override or ignore? I now have it
// and it's already added an unnecessary constriction to my current class :(
}
}
$app = new App();
$app->doSomethingElse(); // The consumer didn't actually want this method
/**
* Scenario 2 is composition. Instead of inheriting everything en masse, I am
* more selective, picking and choosing which behaviour I want.
*/
class App
{
private $service;
public function __construct(ServiceInterface $service)
{
$this->service = $service;
}
public function doSomething()
{
return 'Some custom message ' . $this->service->doSomething();
}
}
$app = new App(new ComplicatedService());
$app->doSomethingElse(); // throws undefined method exception - no side effects :)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment