Example 3

Use case: We need to calculate the price of a booking agency according to the amenities a customer would select during the checkout process Such amenities are WiFi connection, breakfast and OLED TV station in the room. We should also make available to the customer to view his/her amenities.

<?php

interface Booking
{
    public function calculatePrice(int $price): int;

    public function getDescription(): string;
}


class BaseBooking implements Booking
{

    public function calculatePrice(int $price): int
    {
        return $price;
    }

    public function getDescription(): string
    {
        return 'Base booking';
    }
}

And the amenities decorators

<?php

abstract class BaseBookingDecorator implements Booking
{
    protected $booking;

    public function __construct(Booking $booking)
    {
        $this->booking = $booking;
    }

    public function getBooking(): Booking
    {
        return $this->booking;
    }
}

class BreakfastBookingDecorator extends BaseBookingDecorator
{
    public function calculatePrice(int $price): int
    {
        return $this->getBooking()->calculatePrice($price) + 10;
    }

    public function getDescription(): string
    {
        return $this->getBooking()->getDescription() . ' with breakfast';
    }
}

class OledTVBookingDecorator extends BaseBookingDecorator
{
    public function calculatePrice(int $price): int
    {
        return $this->getBooking()->calculatePrice($price) + 1000;
    }

    public function getDescription(): string
    {
        return $this->getBooking()->getDescription() . ' with OLED TV';
    }

}

class WifiBookingDecorator extends BaseBookingDecorator
{
    public function calculatePrice(int $price): int
    {
        return $this->getBooking()->calculatePrice($price) + 10;
    }

    public function getDescription(): string
    {
        return $this->getBooking()->getDescription() . ' with WIFI';
    }
}

Now let the customer to select amenities during checkout (simulation) and return the total calculated price and the list with the amenities

<?php

$booking = new BaseBooking();
$booking = new OledTVBookingDecorator($booking);
$booking = new BreakfastBookingDecorator($booking);
$booking = new WifiBookingDecorator($booking);

echo 'Price: ' . $booking->calculatePrice(10) . PHP_EOL;
echo 'Amenities: ' . $booking->getDescription() . PHP_EOL;

// Output
// Price: 1030
// Amenities: Base booking with OLED TV with breakfast with WIFI


$booking = new BaseBooking();
$booking = new OledTVBookingDecorator($booking);
$booking = new BreakfastBookingDecorator($booking);

echo 'Price: ' . $booking->calculatePrice(10) . PHP_EOL;
echo 'Amenities: ' . $booking->getDescription() . PHP_EOL;

// Output
// Price: 1020
// Amenities: Base booking with OLED TV with breakfast


$booking = new BaseBooking();
$booking = new WifiBookingDecorator($booking);

echo 'Price: ' . $booking->calculatePrice(10) . PHP_EOL;
echo 'Amenities: ' . $booking->getDescription() . PHP_EOL;

// Output
// Price: 20
// Amenities: Base booking with WIFI

$booking = new BaseBooking();

echo 'Price: ' . $booking->calculatePrice(10) . PHP_EOL;
echo 'Amenities: ' . $booking->getDescription() . PHP_EOL;

// Output
// Price: 10
// Amenities: Base booking