Decorator pattern allow us to dynamically extend the behaviour during a runtime, without having to resort to unnecessary inheritance.
interface CarService
{
public function getCost();
public function getDescription();
}
class BasicCarService implements CarService
{
public function getCost()
{
return 10.00;
}
public function getDescription()
{
return 'Basic Car Service';
}
}
class RepairWheelService implements CarService
{
public function __construct(CarService $carService)
{
$this->carService = $carService;
}
public function getCost()
{
return 20 + $this->carService->getCost();
}
public function getDescription()
{
return $this->carService->getDescription() . ' and Repair Wheel';
}
}
class EngineCheckupService implements CarService
{
public function __construct(CarService $carService)
{
$this->carService = $carService;
}
public function getCost()
{
return 50 + $this->carService->getCost();
}
public function getDescription()
{
return $this->carService->getDescription() . ' and Engine Checkup';
}
}
This makes extending a behaviour at runtime dynamic and flexible. For e.g., if we need just Basic Inspection:
echo (new BasicInspection())->getCost();
Basic Inspection and Engine Checkup:
$customerCost = (
new EngineCheckupService(
new BasicCarService
)
);
echo $customerCost->getCost( );
Basic Inspection and Engine Checkup:
$customerCost = (
new EngineCheckupService(
new RepairWheelService(
new BasicCarService
)
)
);
echo $customerCost->getCost( );
class BasicInspection {
public function getCost() {
return 19;
}
}
echo (new BasicInspection())->getCost();
If we need Basic Inspection and Oil Change we have to create another class
class BasicInspectionAndOilChange {
public function getCost() {
return 19 * 19;
}
}
echo (new BasicInspectionAndOilChange())->getCost();
Likewise, if we need Basic Inspection, Oil Change and Tire Rotation - we need to create another class
class BasicInspectionAndOilChangeAndTireRotation {
public function getCost() {
return 19 * 19 + 10;
}
}
echo (new BasicInspectionAndOilChangeAndTireRotation())
->getCost();
Very quicky it breaks down for number of reasons:
Firstly, the number of class required would be huge as many classes are needed for each combination.
Secondly, price are being hardcoded. That means if a Basic Inspection changes to 30, then this has to be updated in multiple places.