<?php
abstract class Coffee {
private $coffeeComponents = [];
public function addComponent(ICoffeeComponent $component) {
$this->coffeeComponents[$type] = $component;
}
protected function getComponent($type) { // Make public if you want access from outside, but you should not really.
throw new InvalidArgumentException(
get_class($this).'::getComponent expects parameter 1 to be string. '.$argType.' given.' );
}
if (!isset($this->coffeeComponents[$type])) { throw new InvalidArgumentException
(get_class($this).' has no component: '.$type); }
return $this->coffeeComponents[$type];
}
}
interface ICoffeeComponent {
// common interface here.
}
class SugarCube implements ICoffeeComponent {
// implement common interface.
// specific stuff.
public function foo() {
echo 'bar';
}
}
class Expresomix implements ICoffeeComponent {
// implement common interface.
// specific stuff.
}
class Beverage extends Coffee {
public function foo() {
$component = $this->getComponent('SugarCube');
$component->foo();
}
}
$coffee = new Beverage();
$coffee->addComponent(new SugarCube());
$coffee->addComponent(new Expresomix());
$coffee->foo();
PD9waHAKYWJzdHJhY3QgY2xhc3MgQ29mZmVlIHsKICAgICAgICBwcml2YXRlICRjb2ZmZWVDb21wb25lbnRzID0gW107CiAKICAgICAgICBwdWJsaWMgZnVuY3Rpb24gYWRkQ29tcG9uZW50KElDb2ZmZWVDb21wb25lbnQgJGNvbXBvbmVudCkgewogICAgICAgICAgICAgICAgJHR5cGUgPSBnZXRfY2xhc3MoJGNvbXBvbmVudCk7CiAgICAgICAgICAgICAgICAkdGhpcy0+Y29mZmVlQ29tcG9uZW50c1skdHlwZV0gPSAkY29tcG9uZW50OwogICAgICAgIH0KIAogICAgICAgIHByb3RlY3RlZCBmdW5jdGlvbiBnZXRDb21wb25lbnQoJHR5cGUpIHsgLy8gTWFrZSBwdWJsaWMgaWYgeW91IHdhbnQgYWNjZXNzIGZyb20gb3V0c2lkZSwgYnV0IHlvdSBzaG91bGQgbm90IHJlYWxseS4KICAgICAgICAgICAgICAgIGlmICghaXNfc3RyaW5nKCR0eXBlKSkgewogICAgICAgICAgICAgICAgICAgICAgICAkYXJnVHlwZSA9IGlzX29iamVjdCgkdHlwZSkgPyBnZXRfY2xhc3MoJHR5cGUpIDogZ2V0dHlwZSgkdHlwZSk7CiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBJbnZhbGlkQXJndW1lbnRFeGNlcHRpb24oCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0X2NsYXNzKCR0aGlzKS4nOjpnZXRDb21wb25lbnQgZXhwZWN0cyBwYXJhbWV0ZXIgMSB0byBiZSBzdHJpbmcuICcuJGFyZ1R5cGUuJyBnaXZlbi4nCiAgICAgICAgICAgICAgICAgICAgICAgICk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBpZiAoIWlzc2V0KCR0aGlzLT5jb2ZmZWVDb21wb25lbnRzWyR0eXBlXSkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEludmFsaWRBcmd1bWVudEV4Y2VwdGlvbihnZXRfY2xhc3MoJHRoaXMpLicgaGFzIG5vIGNvbXBvbmVudDogJy4kdHlwZSk7CiAgICAgICAgICAgICAgICB9CiAKICAgICAgICAgICAgICAgIHJldHVybiAkdGhpcy0+Y29mZmVlQ29tcG9uZW50c1skdHlwZV07CiAgICAgICAgfQp9CiAKaW50ZXJmYWNlIElDb2ZmZWVDb21wb25lbnQgewogICAgICAgIC8vIGNvbW1vbiBpbnRlcmZhY2UgaGVyZS4KfQogCmNsYXNzIFN1Z2FyQ3ViZSBpbXBsZW1lbnRzIElDb2ZmZWVDb21wb25lbnQgewogICAgICAgIC8vIGltcGxlbWVudCBjb21tb24gaW50ZXJmYWNlLgogCiAgICAgICAgLy8gc3BlY2lmaWMgc3R1ZmYuCiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGZvbygpIHsKICAgICAgICAgICAgICAgIGVjaG8gJ2Jhcic7CiAgICAgICAgfQp9CiAKY2xhc3MgRXhwcmVzb21peCBpbXBsZW1lbnRzIElDb2ZmZWVDb21wb25lbnQgewogICAgICAgIC8vIGltcGxlbWVudCBjb21tb24gaW50ZXJmYWNlLgogCiAgICAgICAgLy8gc3BlY2lmaWMgc3R1ZmYuCn0KIApjbGFzcyBCZXZlcmFnZSBleHRlbmRzIENvZmZlZSB7CiAgICAgICAgcHVibGljIGZ1bmN0aW9uIGZvbygpIHsKICAgICAgICAgICAgICAgICRjb21wb25lbnQgPSAkdGhpcy0+Z2V0Q29tcG9uZW50KCdTdWdhckN1YmUnKTsKICAgICAgICAgICAgICAgICRjb21wb25lbnQtPmZvbygpOwogICAgICAgIH0KfQogCiRjb2ZmZWUgPSBuZXcgQmV2ZXJhZ2UoKTsKIAokY29mZmVlLT5hZGRDb21wb25lbnQobmV3IFN1Z2FyQ3ViZSgpKTsKJGNvZmZlZS0+YWRkQ29tcG9uZW50KG5ldyBFeHByZXNvbWl4KCkpOwogCiRjb2ZmZWUtPmZvbygpOw==