interface IConfig {
public function getVar($varName);
public function setVar($varName,$value);
}
interface IConfigParser {
public function parse($filename);
}
// Каждый из нижеперечисленных классов может быть
// оттестирован, отремонтирован, изменен и тп. без
// ущерба для всего остального кода
class IniConfigParser implements IConfigParser { ... }
class XmlConfigParser implements IConfigParser { ... }
class AnotherConfigParser implements IConfigParser { ... }
class FakeConfigParser implements IConfigParser,IConfig { ... }
class ConfigParser {
protected $_parsers = Array();
public function registerParser($fileExtension,IConfigParser $parser) {
$this->_parsers[$fileExtension] = $parser;
}
public function parse($filename) {
// здесь анализируем расширение имени файла и если для такого
// расширения зарегистрирован обработчик, то
return $this->_parsers[$ext]->parse($filename);
}
}
// на этапе инициализации системы это может выглядеть так
$facade = new ConfigParser();
$facade->registerParser('ini',new IniConfigParser());
$facade->registerParser('xml',new XmlConfigParser());
System::getInstance()->setConfigParser($facade);
// ...
$iniConfig = System::getInstance()->getConfigParser()->parse('myconfig.ini');
// через мильен строк кода в непонятном направлении
// мы хотим обмануть некий код, который использует парсер.
// Мы хотим переопределить его поведение, не затрагивая код
// "обманываемого" класса. Мы не трогаем ни этап инициализации,
// ни код существующих классов, все решается
// локально на этом самом месте (с функциями так не получится)
$oldParser = System::getInstance()->getConfigParser();
$fake = new FakeConfigParser($oldParser); // это декоратор. он перекрывает кое-какие значения
$fake->setVar('supportname','Vasya Pupkin');
$fake->setVar('feedbackemail',System::getInstance()->fetchConstant('feedbackemail'));
System::getInstance()->getConfigParser()->registerParser('ini',$fake);
$myObject = new PageController(); // этот класс использует парсер с подставными значениями
$myObject->run();
System::getInstance()->getConfigParser()->registerParser('ini',$oldParser);