Задача на примере.
Есть класс View. Хочется создать класс Cache_View который будет агрегировать внутри себя объект класса $view, а внешне иметь такой же интерфейс как и класс view.
Понятно что на это многие покрутят пальцем у виска, отправят учить ооп, и скажут что нибудь про наследование. Для остальных продолжу мысль.
Простейшая реализация (наследование не подходит, нужно агрегировать)- агрегировать, и определить кучу методов вида
public function xxx($param1,$param2)
{
return $this->agregatedObject->xxx($param1, $param2);
}
?>
Реализация где не придется реализовывать эту кучу методов.
class A
{
public function f1()
{
}
}
class B
{
protected $_a = null;
public function __construct(A $a)
{
$this->_a = $a;
}
public function __call($function, $params)
{
return call_user_func_array(array(&$this->_a, "A::$function"), $params );
}
}
//как работает
$a = A();
$b = B($a);
$a->f1();
$b->f1();// тоже самое что и строчкой выше. Произойдет вызов метода f1 объекта $a
?>
Если кому то еще интересно, ниже пример использования.
class View
{
public function render($template)
{
//return html
}
public function f1()
{
}
//...
public function f120()
{
}
}
class Cache_View
{
protected $_view = null;
protected $_cache = null
public function setCache($cache)
{
$this->_cache = $cache;
}
public function __construct(View $v)
{
$this->_view = $v;
}
public function __call($function, $params)
{
return call_user_func_array(array(&$this->_view, "View::$function"), $params );
}
public function render($template)
{
if ( $this->_cache != null && ! $this->_cache->mis($this->makeKey($template))// если объект кэша есть и в нем чего то лежит
return $this->_cache->get($this->makeKey($template));// то вернем закэшированные данные
$out = $this->_view->render($template);
if ( $this->_cache != null)
$this->_cache->set($this->makeKey($template), $out);
return $out;
}
public function makeKey($str)
{
retirm md5($str);
}
}
//примеры исползования
$view = View();
$cache = Cache::create(Cache::File);
$cachedView = Cached_View($view);
$cachedView->setCache($cache):
$view->test();
$cachedView->test();// тоже самое что и строчкой выше. Вызов метода агрегированного класса
$cachedView->render('splash.php'); // а вот здесь будет предприняты попытка заглянуть в кэш и вернуть закэшированные результаты, если их нет, то произойдет отработка обычного $view->render и результат положится в темплейт
?>
Пример реализации чего то похожего внешне на множественное наследование
class Base()
{
public function base_function() {};
}
class A
{
public function f1()
{
}
}
class B extends Base
{
protected $_a = null;
public function __construct(A $a)
{
$this->_a = $a;
}
public function __call($function, $params)
{
return call_user_func_array(array(&$this->_a, "A::$function"), $params );// понятно что тут можно проверять наличичие метода поочереди у пула объектов, и вызывать их
}
}
$a = new A();
$b = new B($a);
$b->base_function(); //ok child Base
$b->f1(); // looks like child A