Decorator Design Pattern in PHP
In the Decorator pattern, a class will add functionality to another class, without changing the other classes' structure.
In this example, the Book
class will have its title shown in different ways by the BookTitleDecorator
and it's child classes BookTitleExclaimDecorator
and BookTitleStarDecorator
.
In my example I do this by having BookTitleDecorator
make a copy of Book's
title value, which is then changed for display. Depending on the implementation, it might be better to actually change the original object.
<?php
class Book {
private $author;
private $title;
function __construct($title_in, $author_in) {
$this->author = $author_in;
$this->title = $title_in;
}
function getAuthor() {
return $this->author;
}
function getTitle() {
return $this->title;
}
function getAuthorAndTitle() {
return $this->getTitle().' by '.$this->getAuthor();
}
}
class BookTitleDecorator {
protected $book;
protected $title;
public function __construct(Book $book_in) {
$this->book = $book_in;
$this->resetTitle();
}
//doing this so original object is not altered
function resetTitle() {
$this->title = $this->book->getTitle();
}
function showTitle() {
return $this->title;
}
}
class BookTitleExclaimDecorator extends BookTitleDecorator {
private $btd;
public function __construct(BookTitleDecorator $btd_in) {
$this->btd = $btd_in;
}
function exclaimTitle() {
$this->btd->title = "!" . $this->btd->title . "!";
}
}
class BookTitleStarDecorator extends BookTitleDecorator {
private $btd;
public function __construct(BookTitleDecorator $btd_in) {
$this->btd = $btd_in;
}
function starTitle() {
$this->btd->title = Str_replace(" ","*",$this->btd->title);
}
}
writeln('BEGIN TESTING DECORATOR PATTERN');
writeln('');
$patternBook = new Book('Gamma, Helm, Johnson, and Vlissides', 'Design Patterns');
$decorator = new BookTitleDecorator($patternBook);
$starDecorator = new BookTitleStarDecorator($decorator);
$exclaimDecorator = new BookTitleExclaimDecorator($decorator);
writeln('showing title : ');
writeln($decorator->showTitle());
writeln('');
writeln('showing title after two exclaims added : ');
$exclaimDecorator->exclaimTitle();
$exclaimDecorator->exclaimTitle();
writeln($decorator->showTitle());
writeln('');
writeln('showing title after star added : ');
$starDecorator->starTitle();
writeln($decorator->showTitle());
writeln('');
writeln('showing title after reset: ');
writeln($decorator->resetTitle());
writeln($decorator->showTitle());
writeln('');
writeln('END TESTING DECORATOR PATTERN');
function writeln($line_in) {
echo $line_in."<br/>";
}
?>
Output
BEGIN TESTING DECORATOR PATTERN showing title : Design Patterns showing title after two exclaims added : !!Design Patterns!! showing title after star added : !!Design*Patterns!! showing title after reset: Design Patterns END TESTING DECORATOR PATTERN