De ocioso he estado analizando un par de patrones de diseño y me he topado con un problema en un ejemplo del Decorator Pattern.
El problema es que no funciona como debería, en las subclasses de la clase decorator "String_Formatter" solo ejecuta con exito la 1º, osea String_Formatter_Uppercase, en las restantes hijas el metodo getString del padre obtiene un nulo.
La salida en el metodo output debiese ser "PATTERNS FOR PHP"
Aqui dejo el ejemplo haber si alguien más experimentado que yo me ayuda a encontrar la correcta solución.
La fuente del ejemplo lo he sacado de patternsforphp.com.
Código PHP:
<?php
class String_Writer {
private $path = '';
private $string = '';
public function __construct($path) {
$this->path = $path;
}
public function setString($string) {
$this->string = $string;
}
public function getString() {
return $this->string;
}
public function getPath() {
return $this->path;
}
public function store() {
// we assume one string per line
if(!file_put_contents($this->path, $this->string . PHP_EOL, FILE_APPEND))
{
throw new Exception('Error writing to specified path');
}
}
}
class String_Formatter {
private $string = '';
public function __construct(String_Writer $writer) {
$this->string = $writer->getString();
}
public function getString() {
return $this->string;
}
public function setString($string) {
$this->string = $string;
}
public function output() {
return $this->string;
}
}
interface iString_Formatter {
public function format();
}
class String_Formatter_Uppercase extends String_Formatter implements iString_Formatter {
private $stringFormatter;
public function __construct(String_Formatter $stringFormatter) {
$this->stringFormatter = $stringFormatter;
}
public function format() {
$this->stringFormatter->setString(
strtoupper($this->stringFormatter->getString())
);
}
}
class String_Formatter_Reverse extends String_Formatter implements iString_Formatter {
private $stringFormatter;
public function __construct(String_Formatter $stringFormatter) {
$this->stringFormatter = $stringFormatter;
//print $this->stringFormatter->getString().'X';
}
public function format() {
$this->stringFormatter->setString(
strrev($this->stringFormatter->getString())
);
}
}
class String_Formatter_Escape extends String_Formatter implements iString_Formatter {
private $stringFormatter;
public function __construct(String_Formatter $stringFormatter) {
$this->stringFormatter = $stringFormatter;
}
public function format() {
$this->stringFormatter->setString(
htmlentities($this->stringFormatter->getString(), ENT_QUOTES, 'UTF-8')
);
}
}
/*
require('String_Writer.php');
require('String_Formatter.php');
require('iString_Formatter.php');
require('String_Formatter_Uppercase.php');
require('String_Formatter_Reverse.php');
require('String_Formatter_Escape.php');
*/
$string = 'php rof snrettap';
$path = './stringlog';
/*
Create a new String_Writer object
*/
$stringWriter = new String_Writer($path);
$stringWriter->setString($string);
/*
Store the string to a file
*/
$stringWriter->store();
/*
Instantiate a String_Formatter object to control output
*/
$stringFormatter = new String_Formatter($stringWriter);
/*
Instantiate specific String_Formatters. Pass in String_Formatter object
as parameter to first Formatter. Pass new Formatter into third, etc.
This chained set of parameters links all the Formatters to the same string.
*/
$stringUppercase = new String_Formatter_Uppercase($stringFormatter);
$stringReverse = new String_Formatter_Reverse($stringUppercase);
$stringEscape = new String_Formatter_Escape($stringReverse);
/*
Perform the formatting, call format() method of each required Formatting option
*/
$stringUppercase->format();
$stringReverse->format();
$stringEscape->format();
/*
Return the results for output
*/
print $stringFormatter->output();
//$output = $stringFormatter->output();
/*
Exit the script while printing the resulting formatted string (which is also
stored in our log file in original form)
*/
//exit($output); // PATTERNS FOR PHP (reversed, uppercased and escaped!)
?>