I'm not sure how php execute this decorator design pattern example. the problem is when I use return in the operation function it gets called from down to up and when using echo in the operation function it gets called from up to down like the code below. I don't understand how this behavior works.
echo behavior
<?php
interface IBaseInterface {
public function operation();
}
class BaseComponent implements IBaseInterface{
public function operation(){
echo "baseComponent";
}
}
class baseDecorator implements IBaseInterface {
protected $component;
public function __construct(IBaseInterface $component){
$this->component = $component;
}
public function operation(){
echo $this->component->operation();
}
}
class concreteDecoratorA extends baseDecorator {
public function operation(){
echo "ConcreteDecoratorA(". parent::operation() . ")";
}
}
class concreteDecoratorB extends baseDecorator {
public function operation(){
echo "ConcreteDecoratorB(". parent::operation() . ")";
}
}
$simple = new BaseComponent();
$decorator1 = new concreteDecoratorA($simple);
$decorator2 = new concreteDecoratorB($decorator1);
$decorator2->operation();
?>
output
baseComponentConcreteDecoratorA()ConcreteDecoratorB()
** return behavior**
<?php
interface IBaseInterface {
public function operation();
}
class BaseComponent implements IBaseInterface{
public function operation(){
return "baseComponent";
}
}
class baseDecorator implements IBaseInterface {
protected $component;
public function __construct(IBaseInterface $component){
$this->component = $component;
}
public function operation(){
return $this->component->operation();
}
}
class concreteDecoratorA extends baseDecorator {
public function operation(){
return "ConcreteDecoratorA(". parent::operation() . ")";
}
}
class concreteDecoratorB extends baseDecorator {
public function operation(){
return "ConcreteDecoratorB(". parent::operation() . ")";
}
}
$simple = new BaseComponent();
$decorator1 = new concreteDecoratorA($simple);
$decorator2 = new concreteDecoratorB($decorator1);
echo $decorator2->operation();
?>
output
ConcreteDecoratorB(ConcreteDecoratorA(baseComponent))
CodePudding user response:
The call stack doesn't change. But what the methods do changes. When you echo
something, it outputs immediately. When you return
something, the calling code shown outputs the value later.
Consider the semantics of this statement:
echo "ConcreteDecoratorB(". parent::operation() . ")";
It can be interpreted as:
- Do
parent::operation()
first, whatever it does. - Whatever
parent::operation()
returned, concatenate it to this string. - Output this string.
So if parent::operation()
outputs a string but returns nothing then the result will be whatever parent::operation()
outputs is printed to the screen, then this string literal is printed to the screen.
Alternatively, consider the semantics of this:
return "ConcreteDecoratorB(". parent::operation() . ")";
Which is:
- Do
parent::operation()
first, whatever it does. - Whatever
parent::operation()
returned, concatenate it to this string. - Return this string.
In thie case, Step 3 changed, but your implementation of parent::operation()
is also different in that example. So if parent::operation()
returns a string then so far nothing has been outputted. That returned string is concatenated into this string, and the whole combined string is returned.
Calling code then outputs it at the very end:
echo $decorator2->operation();
Ultimately, the difference is between printing a string now and returning nothing vs. returning a string to be combined with other strings and printed later.
The call stack is the same either way. You're just doing two logically different things in your operations.