mirror of
https://github.com/DesignPatternsPHP/DesignPatternsPHP.git
synced 2025-08-03 21:47:25 +02:00
refactored Decorator pattern
This commit is contained in:
10
Structural/Decorator/Booking.php
Normal file
10
Structural/Decorator/Booking.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Structural\Decorator;
|
||||
|
||||
interface Booking
|
||||
{
|
||||
public function calculatePrice(): int;
|
||||
|
||||
public function getDescription(): string;
|
||||
}
|
16
Structural/Decorator/BookingDecorator.php
Normal file
16
Structural/Decorator/BookingDecorator.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Structural\Decorator;
|
||||
|
||||
abstract class BookingDecorator implements Booking
|
||||
{
|
||||
/**
|
||||
* @var Booking
|
||||
*/
|
||||
protected $booking;
|
||||
|
||||
public function __construct(Booking $booking)
|
||||
{
|
||||
$this->booking = $booking;
|
||||
}
|
||||
}
|
16
Structural/Decorator/DoubleRoomBooking.php
Normal file
16
Structural/Decorator/DoubleRoomBooking.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Structural\Decorator;
|
||||
|
||||
class DoubleRoomBooking implements Booking
|
||||
{
|
||||
public function calculatePrice(): int
|
||||
{
|
||||
return 40;
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'double room';
|
||||
}
|
||||
}
|
18
Structural/Decorator/ExtraBed.php
Normal file
18
Structural/Decorator/ExtraBed.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Structural\Decorator;
|
||||
|
||||
class ExtraBed extends BookingDecorator
|
||||
{
|
||||
private const PRICE = 30;
|
||||
|
||||
public function calculatePrice(): int
|
||||
{
|
||||
return $this->booking->calculatePrice() + self::PRICE;
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return $this->booking->getDescription() . ' with extra bed';
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Structural\Decorator;
|
||||
|
||||
class JsonRenderer extends RendererDecorator
|
||||
{
|
||||
public function renderData(): string
|
||||
{
|
||||
return json_encode($this->wrapped->renderData());
|
||||
}
|
||||
}
|
@@ -25,33 +25,33 @@ Code
|
||||
|
||||
You can also find this code on `GitHub`_
|
||||
|
||||
RenderableInterface.php
|
||||
Booking.php
|
||||
|
||||
.. literalinclude:: RenderableInterface.php
|
||||
.. literalinclude:: Booking.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
Webservice.php
|
||||
BookingDecorator.php
|
||||
|
||||
.. literalinclude:: Webservice.php
|
||||
.. literalinclude:: BookingDecorator.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
RendererDecorator.php
|
||||
DoubleRoomBooking.php
|
||||
|
||||
.. literalinclude:: RendererDecorator.php
|
||||
.. literalinclude:: DoubleRoomBooking.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
XmlRenderer.php
|
||||
ExtraBed.php
|
||||
|
||||
.. literalinclude:: XmlRenderer.php
|
||||
.. literalinclude:: ExtraBed.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
JsonRenderer.php
|
||||
WiFi.php
|
||||
|
||||
.. literalinclude:: JsonRenderer.php
|
||||
.. literalinclude:: WiFi.php
|
||||
:language: php
|
||||
:linenos:
|
||||
|
||||
|
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Structural\Decorator;
|
||||
|
||||
interface RenderableInterface
|
||||
{
|
||||
public function renderData(): string;
|
||||
}
|
@@ -1,24 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Structural\Decorator;
|
||||
|
||||
/**
|
||||
* the Decorator MUST implement the RenderableInterface contract, this is the key-feature
|
||||
* of this design pattern. If not, this is no longer a Decorator but just a dumb
|
||||
* wrapper.
|
||||
*/
|
||||
abstract class RendererDecorator implements RenderableInterface
|
||||
{
|
||||
/**
|
||||
* @var RenderableInterface
|
||||
*/
|
||||
protected $wrapped;
|
||||
|
||||
/**
|
||||
* @param RenderableInterface $renderer
|
||||
*/
|
||||
public function __construct(RenderableInterface $renderer)
|
||||
{
|
||||
$this->wrapped = $renderer;
|
||||
}
|
||||
}
|
@@ -2,32 +2,37 @@
|
||||
|
||||
namespace DesignPatterns\Structural\Decorator\Tests;
|
||||
|
||||
use DesignPatterns\Structural\Decorator;
|
||||
use DesignPatterns\Structural\Decorator\DoubleRoomBooking;
|
||||
use DesignPatterns\Structural\Decorator\ExtraBed;
|
||||
use DesignPatterns\Structural\Decorator\WiFi;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DecoratorTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var Decorator\Webservice
|
||||
*/
|
||||
private $service;
|
||||
|
||||
protected function setUp()
|
||||
public function testCanCalculatePriceForBasicDoubleRoomBooking()
|
||||
{
|
||||
$this->service = new Decorator\Webservice('foobar');
|
||||
$booking = new DoubleRoomBooking();
|
||||
|
||||
$this->assertEquals(40, $booking->calculatePrice());
|
||||
$this->assertEquals('double room', $booking->getDescription());
|
||||
}
|
||||
|
||||
public function testJsonDecorator()
|
||||
public function testCanCalculatePriceForDoubleRoomBookingWithWiFi()
|
||||
{
|
||||
$service = new Decorator\JsonRenderer($this->service);
|
||||
$booking = new DoubleRoomBooking();
|
||||
$booking = new WiFi($booking);
|
||||
|
||||
$this->assertEquals('"foobar"', $service->renderData());
|
||||
$this->assertEquals(42, $booking->calculatePrice());
|
||||
$this->assertEquals('double room with wifi', $booking->getDescription());
|
||||
}
|
||||
|
||||
public function testXmlDecorator()
|
||||
public function testCanCalculatePriceForDoubleRoomBookingWithWiFiAndExtraBed()
|
||||
{
|
||||
$service = new Decorator\XmlRenderer($this->service);
|
||||
$booking = new DoubleRoomBooking();
|
||||
$booking = new WiFi($booking);
|
||||
$booking = new ExtraBed($booking);
|
||||
|
||||
$this->assertXmlStringEqualsXmlString('<?xml version="1.0"?><content>foobar</content>', $service->renderData());
|
||||
$this->assertEquals(72, $booking->calculatePrice());
|
||||
$this->assertEquals('double room with wifi with extra bed', $booking->getDescription());
|
||||
}
|
||||
}
|
||||
|
@@ -1,21 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Structural\Decorator;
|
||||
|
||||
class Webservice implements RenderableInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $data;
|
||||
|
||||
public function __construct(string $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
public function renderData(): string
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
}
|
18
Structural/Decorator/WiFi.php
Normal file
18
Structural/Decorator/WiFi.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Structural\Decorator;
|
||||
|
||||
class WiFi extends BookingDecorator
|
||||
{
|
||||
private const PRICE = 2;
|
||||
|
||||
public function calculatePrice(): int
|
||||
{
|
||||
return $this->booking->calculatePrice() + self::PRICE;
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return $this->booking->getDescription() . ' with wifi';
|
||||
}
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace DesignPatterns\Structural\Decorator;
|
||||
|
||||
class XmlRenderer extends RendererDecorator
|
||||
{
|
||||
public function renderData(): string
|
||||
{
|
||||
$doc = new \DOMDocument();
|
||||
$data = $this->wrapped->renderData();
|
||||
$doc->appendChild($doc->createElement('content', $data));
|
||||
|
||||
return $doc->saveXML();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user