[TYPO3-ect] News about XCLASSES?

Joerg Schoppet joerg at schoppet.de
Thu Aug 24 07:29:02 CEST 2006


Oliver Hader wrote:
> Ernesto Baschny [cron IT] wrote:
>> You create a new class that implements the complete interface of the
>> original class (i.e. it provides all methods from the "inherited"
>> class). The constructor gets an instance of the original class and you
>> start with calling all original methods on that instance that you get
>> passed. Then you can simply add or change or enhance certain methods to
>> do what you want it to do. As the constructor gets an instance of the
>> class with the same interface, it is easy to "chain" together many classes.
> 
> That's true. Real decorators must have the complete interface as it is
> present the decorated class. But in PHP5 we could use something new, the
> __call($method, $args) for calling the method from the decorated class.
> 
> I've created a small example on the decorator usage. Decorators have
> appropriate class names, the decorated classes a called "Components".
> In that example it's possible to build up a multi-functional-object that
> has all functionallity of the component class and all involved
> decorators. I removed some stuff, just to get the idea, the complete
> code is shown at http://devel.t3ip.de/decorator.php.txt.
> 
> So here we go:
> 
> 
> $digitComponent = new DigitComponent(16, 2);
> // give it a try, and create a "hyper" functional class
> $hyperObject =
> new SummateDecorator(
> 	new DivideDecorator(
> 		new MultiplyDecorator(
> 			$digitComponent
> 		)
> 	)
> );
> $hyperObject->divide();
> $hyperObject->multiply();
> $hyperObject->summate();
> $hyperObject->show();
> 
> 
> /**
>  * Here come the components we are working on.
>  * This could be any type of content.
>  */
> abstract class Component {
> 	public $content = '';
> 
> 	public function show() {}
> 	public function addBR() {}
> }
> 
> class DigitComponent extends Component {
> 	public $numberA;
> 	public $numberB;
> 	public function __construct($numberA, $numberB) {}
> }
> 
> /**
>  * Here come our decorators playing with the components in some way.
>  */
> abstract class Decorator extends Component {
> 	protected $component;
> 
> 	public function __construct(Component &$component) {
> 		$this->component =& $component;
> 	}
> 	
> 	public function show() {
> 		// call the show method of the component
> 		$this->component->show();
> 	}
> 
> 	public function __call($method, $args) {
> 		// fetch calls to currenty unsupported methods an try
> 		// on the decorated component
> 		call_user_method($method, $this->component, $args);
> 	}
> 	
> 	public function getComponent() {
> 		$component =& $this->component;
> 
> 		// iterate out of decorators up to the component
> 		while ($component instanceof Decorator)
> 			$component =& $component->component;
> 
> 		// return the component so we can work on it
> 		return $component;
> 	}
> }
> 
> class MultiplyDecorator extends Decorator {
> 	public function multiply() {}
> }
> 
> class DivideDecorator extends Decorator {
> 	public function divide() {}
> }
> 
> class SummateDecorator extends Decorator {
> 	public function summate() {}
> }
> 
> 
> So you can see, that the methods divide, summate, multiply are sticked
> together with several decorator classes. Probably someone finds some
> errors in my "two decorator-cents", but it should just show, how it
> could work.
> 
> 
>> When TYPO3 then needs to create a cObj and our extension has
>> "registered" somehow that we provide an enhancement to it, the
>> makeInstance method just has to chain that together:
>>
>> function &makeInstance($className) {
>>   $obj =& new $className;
>>   $decorators =
>> $GLOBALS['TYPO3_CONF_VARS']['SYS']['OBJ_DECORATORS'][$className];
>>   foreach ($decorators as $dec) {
>>     $obj =& new $dec($obj);
>>   }
>>   return $obj;
>> }
>>
>> This is untested, I just made it out! :)
>>
> 
> I also didn't check this, but I'm sure that this will work! ;)
> 
> On using decorators the system would get very complex very fast. So if
> there is no documentation or "plan" how to use decorators in TYPO3, give
> it some months and nobody knows again which decorator solves which problem.
> An advantage is that you could build your own objects, depending on your
> special demands. The disadvantage could be, that laziness finds it's way
> it that topic and everything is fired up using all available decorators
> and kills performace step by step.
> 
> But I like the idea of using design patterns in general - as you all can
> imagine, "decorator" is not the only one out there... ;)
> 
> 
> Regards,
> Olly

Hi,

this is nearly the solution I'm working on. A combination of Olly's and 
Ernesto's thoughts.

I've a general registry-object. Each extension, which wants to provide a 
decorator for a given class has to register its classes (decorators) in 
the registry-object informing about the class it wants to extend 
(through a method-call in ext_localconf.php), the classes its depend on 
and classes its conflicts with.
As a developer I can then simple call a factory-method of the 
registry-object, informing about the class I want and which additional 
functionality I want, and the factory-method then automatically resolves 
all necessary dependencies and decorator-chains and return a new object.

With the technique of registering, it could also be possible to create a 
little backend-module, which shows the available decorators (like the 
sv_auth be-module in TYPO3 3.7).

Joerg



More information about the TYPO3-team-extension-coordination mailing list