Как-то медитируя на свой новый велосипед подумал, – А почему бы не заложить в него возможность «плагинизации» контроллеров?
Чтобы вот был, например, у нас некий базовый класс Generic.php:
А мы такие взяли и повешали бы на него пару плагинов, которые дополнят/изменят какие-либо его методы не мешая друг-другу (по принципу «кто первый встал – того и тапки»).
Вот они красавцы:
PluginFoo.php:
и PluginBar.php:
А потом мы создали бы объект родительского класса (не обращаясь к последнему потомку), вызвали метод Hello() и тот сказал бы нам:
Ниже лаконичный вариант того как описанного поведения добился ort в своём LiveStreet, а затем уже и я в своём собственном велосипеде.
Вы наверное уже заметили в коде выше, что классы плагинов PluginFoo и PluginBar наследуются от неописанных классов Generic_PluginFoo и Generic_PluginBar соответственно? Так вот их и не будет вообще. Этот финт ушами нам нужен для классалиасинга и выстраивания цепочки наследования.
Да чего резину тянуть.
Вот пример использования:
// Получим
// Dudes?
// Hello!
// O.o
Волшебный инструмент:
И вот у меня вопрос, – Как это называется на «языке паттернов»? Как бы вы это назвали?
P.S. Разумеется — этот пост является следствием первоапрельского розыгрыша с ППА :)
– Та-да!
Чтобы вот был, например, у нас некий базовый класс Generic.php:
<?php
class Generic
{
public function Hello() {
echo 'Hello!';
}
}
?>
А мы такие взяли и повешали бы на него пару плагинов, которые дополнят/изменят какие-либо его методы не мешая друг-другу (по принципу «кто первый встал – того и тапки»).
Вот они красавцы:
PluginFoo.php:
<?php
class PluginFoo extends Generic_PluginFoo
{
public function Hello() {
echo 'Dudes?<br />';
parent::Hello();
}
}
?>
и PluginBar.php:
<?php
class PluginBar extends Generic_PluginBar
{
public function Hello() {
parent::Hello();
echo '<br />O.o';
}
}
?>
А потом мы создали бы объект родительского класса (не обращаясь к последнему потомку), вызвали метод Hello() и тот сказал бы нам:
Dudes?
Hello!
O.o
Ниже лаконичный вариант того как описанного поведения добился ort в своём LiveStreet, а затем уже и я в своём собственном велосипеде.
Вы наверное уже заметили в коде выше, что классы плагинов PluginFoo и PluginBar наследуются от неописанных классов Generic_PluginFoo и Generic_PluginBar соответственно? Так вот их и не будет вообще. Этот финт ушами нам нужен для классалиасинга и выстраивания цепочки наследования.
Да чего резину тянуть.
Вот пример использования:
// создаём объект (Ваш Капитан Очевидность)
$KungFu = new KungFu();
// Регистрируем плагин PluginFoo для базового класса Generic
$KungFu->RegisterPlugin('Generic', 'PluginFoo');
// Регистрируем плагин PluginBar для базового класса Generic
$KungFu->RegisterPlugin('Generic', 'PluginBar');
// Загружаем <i>отплагинизированный</i> объект класса Generic
$Generic = $KungFu->Load('Generic');
$Generic->Hello();
// Получим
// Dudes?
// Hello!
// O.o
Волшебный инструмент:
class KungFu
{
// Эээ... Конструктор
public function __construct() {
spl_autoload_register(array($this, '_AutoLoader'));
}
// Эээ... Метод автозагрузки
public function _AutoLoader($sClass)
{
if (false == class_exists($sClass)) {
include($sClass.'.php');
}
}
// после регистрации плагинов примет вид
// Array ( [Generic] => Array ( [0] => PluginFoo [1] => PluginBar ) )
private $_aPlugins = array();
// Метод регистрации плагинов, заполняющий массив, что описан выше
public function RegisterPlugin($sClass, $sPlugin)
{
if (false == isset($this->_aPlugins[$sClass])) {
$this->_aPlugins[$sClass] = array();
}
array_push($this->_aPlugins[$sClass], $sPlugin);
}
// Метод вернет объект указанного класса. Если для этого класса указаны плагины, то разумеется объект будет по пути плагинизирован.
public function Load($sClass)
{
if (false == isset($this->_aPlugins[$sClass])) {
return new $sClass();
}
else
{
$aPlugins = array_reverse($this->_aPlugins[$sClass]);
$sPrev = null;
foreach ($aPlugins as $sPlugin)
{
if (null != $sPrev) {
$aBranch[$sPrev] = $sPlugin;
}
$aBranch[$sPlugin] = null;
$sPrev = $sPlugin;
}
$aBranch[$sPrev] = $sClass;
foreach (array_reverse($aBranch) as $sPlugin => $sParent) {
class_alias($sParent, $sClass.'_'.$sPlugin);
}
if (class_exists($sPlugin)) {
return new $sPlugin;
}
}
}
}
И вот у меня вопрос, – Как это называется на «языке паттернов»? Как бы вы это назвали?
P.S. Разумеется — этот пост является следствием первоапрельского розыгрыша с ППА :)
– Та-да!