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.