The delegation pattern is a basic technique in software design patterns. In the delegation pattern, two objects participate in processing the same request, and the object accepting the request delegates the request to another object for processing. The delegation pattern is a basic technique, and many other patterns, such as the state pattern, strategy pattern, and visitor pattern, essentially use the delegation pattern in more special occasions.
Introduction to dynamic delegation: The concept of dynamic delegation comes from the Jakarta Byte-Code Engineering Library (BCEL). It can analyze existing classes and, for interfaces, abstract classes, and even runtime concrete classes, it can generate byte-encoded delegate classes.
The delegated interface/class should meet the following conditions: dynamic delegation can only delegate at most one class, but can proxy multiple interfaces. This limitation comes from Java's single inheritance model. A Java class has at most one parent class. Since the generated delegation class takes the delegated class as its parent class, it is unreasonable to specify multiple delegated classes. If the delegated class is not specified, the default parent class is Object.
The following is the code for implementing dynamic proxy using PHP reflection mechanism:
<?php class Fruit { function callFruit() { print "Generate an Apple"; } } class FruitDelegator { private $targets; function __construct() { $this->target[] = new Fruit(); } function __call($name, $args) { foreach ($this->target as $obj) { $r = new ReflectionClass($obj); if ($method = $r->getMethod($name)) { if ($method->isPublic() && !$method->isAbstract()) { return $method->invoke($obj, $args); } } } } } $obj = new FruitDelegator(); $obj->callFruit(); // 运行结果 // Generate an Apple ?>
It can be seen that its method is implemented through the proxy class FruitDelegator instead of the Fruit class.
Similarly, the following code can also be run:
<?php class Color { function callColor() { print "Generate Red"; } } class ColorDelegator { private $targets; function addObject($obj) { $this->target[] = $obj; } function __call($name, $args) { foreach ($this->target as $obj) { $r = new ReflectionClass($obj); if ($method = $r->getMethod($name)) { if ($method->isPublic() && !$method->isAbstract()) { return $method->invoke($obj, $args); } } } } } $obj = new ColorDelegator(); $obj->addObject(new Color()); $obj->callColor(); ?>