Search code examples
phpchaining

Can't change parent variable in chain responsibility pattern


I used the chain responsibility pattern and I completely learned it but when I wanted to implement some counter that after the task is done and next task is going to be called, that is not working, I wanted to make a counter to count the tasks that are done... I have 3 classes named lights, alarms, locks and in last part of check method in all of those, I call next method to check method in next object, I incremented the counter variable in parent class in next method but I don't know why the output is 5,5,5.. this is the code anyhow:

abstract class HomeChecker {
protected $successor;
protected $counter = 0;
public abstract function check(HomeStatus $home);
public function succeedWith(HomeChecker $successor)
{
    $this->successor = $successor;
}
public function next(HomeStatus $home)
{
    **$this->counter += 5;
    var_dump($this->counter);**
    if ($this->successor)
    {
        $this->successor->check($home);
    }
}
}

class Locks extends HomeChecker{
public function check(HomeStatus $home)
{
   **//some code
    $this->next($home);**
}
public function hello(){
    return $this->counter;
}
}
class HomeStatus {
public $alarmOn = true;
public $locked = true;
public $lightsOff = true;
}
$locks = new Locks;
$lights = new Lights;
$alarm = new Alarm;
$locks->succeedWith($lights);
$lights->succeedWith($alarm);
$status = new HomeStatus;
$locks->check($status);
echo $lights->hello();
echo $alarm->hello();
echo $locks->hello();

after that, I have 5,5,5 and that is weird because the next method has been called 3 times that it should increment the counter variable 3 times by 5 which makes it 15. Am I wrong? thank you.


Solution

  • Every instance of Locks, Lights and Alarm has its own independent copy of the protected property $counter, inherited from HomeChecker. The counter is not shared, which is why each instance has a counter value of 5.

    One approach to sharing a single counter between all instances of these classes would be to use a static property of HomeChecker:

    abstract class HomeChecker
    {
    
        // ...
    
        protected static $counter = 0;
    
        // ...
    
        public function next(HomeStatus $home)
        {
            self::$counter += 5;
            var_dump(self::$counter);
            if ($this->successor)
            {
                $this->successor->check($home);
            }
        }
    
        // ...
    }
    
    class Locks extends HomeChecker
    {
    
        // ...
    
        public function hello(){
            return self::$counter;
        }
    
        // ...
    }
    

    These changes will give you the output 15 that you're expecting, as the static property $counter is now shared. You can read more about static properties in the manual http://php.net/manual/en/language.oop5.static.php