State Design Pattern in PHP
In the State Pattern a class will change it's behavior when circumstances change.
In this example, the BookContext
class holds an implementation of the BookTitleStateInterface
, starting with BookTitleStateStars
. BookTitleStateStars
and BookTitleStateExclaim
will then replace each other in BookContext
depending on how many times they are called.
<?php
class BookContext {
private $book = NULL;
private $bookTitleState = NULL;
//bookList is not instantiated at construct time
public function __construct($book_in) {
$this->book = $book_in;
$this->setTitleState(new BookTitleStateStars());
}
public function getBookTitle() {
return $this->bookTitleState->showTitle($this);
}
public function getBook() {
return $this->book;
}
public function setTitleState($titleState_in) {
$this->bookTitleState = $titleState_in;
}
}
interface BookTitleStateInterface {
public function showTitle($context_in);
}
class BookTitleStateExclaim implements BookTitleStateInterface {
private $titleCount = 0;
public function showTitle($context_in) {
$title = $context_in->getBook()->getTitle();
$this->titleCount++;
$context_in->setTitleState(new BookTitleStateStars());
return Str_replace(' ','!',$title);
}
}
class BookTitleStateStars implements BookTitleStateInterface {
private $titleCount = 0;
public function showTitle($context_in) {
$title = $context_in->getBook()->getTitle();
$this->titleCount++;
if (1 < $this->titleCount) {
$context_in->setTitleState(new BookTitleStateExclaim);
}
return Str_replace(' ','*',$title);
}
}
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();
}
}
writeln('BEGIN TESTING STATE PATTERN');
writeln('');
$book = new Book('PHP for Cats','Larry Truett');;
$context = new bookContext($book);
writeln('test 1 - show name');
writeln($context->getBookTitle());
writeln('');
writeln('test 2 - show name');
writeln($context->getBookTitle());
writeln('');
writeln('test 3 - show name');
writeln($context->getBookTitle());
writeln('');
writeln('test 4 - show name');
writeln($context->getBookTitle());
writeln('');
writeln('END TESTING STATE PATTERN');
function writeln($line_in) {
echo $line_in."<br/>";
}
?>
Output
BEGIN TESTING STATE PATTERN test 1 - show name PHP*for*Cats test 2 - show name PHP*for*Cats test 3 - show name PHP!for!Cats test 4 - show name PHP*for*Cats END TESTING STATE PATTERN