動的Proxy
オブジェクト生成時のいろいろな指定はとりあえず無視しとく。
function p($s)
{
echo $s . "\n";
}
class Object
{
function __get($name)
{
if (!isset($this->{$name})) {
$this->{$name} = new $name();
}
return $this->{$name};
}
}
class foo extends Object
{
//var $bar; 指定してしまうと__getが使えないのがネックかも
function __construct()
{
p('foo::construct');
}
function hoge($s)
{
p('foo::hoge');
return $this->bar->hoge($s.'foo');
}
}
class bar extends Object
{
//var $baz;
function __construct()
{
p('bar::construct');
}
function hoge($s)
{
p('bar::uni');
return $this->baz->hoge($s.'|bar');
}
}
class baz
{
function __construct()
{
p('baz::construct');
}
function hoge($s)
{
p('baz::uni');
return $s.'|baz';
}
}
メリット
- シンプル
- 余計なオブジェクト(プロキシクラス含む)を生成しない
デメリット
- 親クラスを継承する必要がある
- プロパティに指定を書けない
function p($s)
{
echo "$s\n";
}
class Container
{
static function create($class)
{
$result = new $class();
foreach ($result as $p => $v) {
$result->{$p} = new Proxy($p);
}
return $result;
}
}
class foo
{
var $bar;//Proxy
function __construct()
{
p('foo::construct');
}
function hoge($s)
{
p('foo::hoge');
return $this->bar->hoge($s.'|foo');
}
}
class bar
{
var $baz;
function __construct()
{
p('bar::construct');
}
function hoge($s)
{
p('bar::hoge');
return $this->baz->hoge($s.'|bar');
}
}
class baz
{
function __construct()
{
p('baz::construct');
}
function hoge($s)
{
p('baz::hoge');
return $s.'|baz';
}
}
class Proxy
{
private $ref;
private $instance;
function __construct($class)
{
$this->ref = new ReflectionClass($class);
}
function __get($name)
{
if (!isset($this->instance)) {
$this->__instantiate();
}
return $this->instance->{$name};
}
function __set($name, $value)
{
if (!isset($this->instance)) {
$this->__instantiate();
}
$this->instance->{$name} = $value;
}
function __call($name, $args)
{
if (!$this->ref->hasMethod($name)) {
// error
echo "error\n";
}
if (!isset($this->instance)) {
$this->__instantiate();
}
return $this->ref->getMethod($name)->invokeArgs($this->instance, $args);
}
function __instantiate()
{
$this->instance = Container::create($this->ref->getName());
}
}
$foo = Container::create('foo');
p ($foo->hoge('ccc') );