-
-
Save mhlavac/465a0efc33ddaae61218 to your computer and use it in GitHub Desktop.
| <?php | |
| interface Greeter | |
| { | |
| public function greet($name); | |
| } | |
| class ChainGreeter implements Greeter | |
| { | |
| private $greeters = []; | |
| public function addGreeter(Greeter $greeter) | |
| { | |
| $this->greeters[] = $greeter; | |
| } | |
| public function greet($name) | |
| { | |
| foreach ($this->greeters as $greeter) { | |
| $greeter->greet($name); | |
| } | |
| } | |
| } | |
| class StringGreeter() implements Greeter | |
| { | |
| private $sentence; | |
| public function __construct($sentence) | |
| { | |
| $this->sentence = $sentence; | |
| } | |
| public function greet($name) | |
| { | |
| spritnf($sentence, $name); | |
| } | |
| } | |
| $chainGreeter = new ChainGreeter(); | |
| $chainGreeter->add(new StringGreeter('Hello %s')); | |
| $chainGreeter->add(new StringGreeter('Good morning %s')); | |
| $chainGreeter->greet('John Doe'); |
Jakub I like your approach, it's a nice way how to separate responsibilities and btw. another name for original Chain can be also Collection ;-)
@mhlavac I see Collection as a collection of objects being on the same level, but the Chain is an object inside an object inside an object (auto na auta na auta) :-).
@jakubzapletal exactly, or at least if there is a foreach that goes over inner objects it ends as soon as it finds one. Like this example from ChainUserProvider:
/**
* {@inheritdoc}
*/
public function loadUserByUsername($username)
{
foreach ($this->providers as $provider) {
try {
return $provider->loadUserByUsername($username);
} catch (UsernameNotFoundException $notFound) {
// try next one
}
}
$ex = new UsernameNotFoundException(sprintf('There is no user with name "%s".', $username));
$ex->setUsername($username);
throw $ex;
}@mhlavac accurate example of Chain of Responsibilities
This is not Chain of Responsibility pattern: https://en.wikipedia.org/wiki/Chain-of-responsibility_pattern This is Composite: https://en.wikipedia.org/wiki/Composite_pattern
Haha the naming problem :)
Would agree with @pavel-dohnal-momentumft. To me this seems like the composite pattern.
So CompositeGreeter? 😄
@pavel-dohnal-momentumft I also thought it's a composite, because this is how usuall composites are implemented.
So in the end I came with 2 ideas.
Command where we can use just __invoke. So it feels almost like named closure.
class GreetCommand
{
/**
* @var Greeter[]
*/
private $greeters;
public function __construct(array $greeters = [])
{
$this->greeters = $greeters;
}
public function __invoke($name)
{
foreach ($this->greeters as $greeter) {
$greeter->greet($name);
}
}
}And simple Greeters, because it's just multiple Greeters anyway.
class Greeters
{
/**
* @var Greeter[]
*/
private $greeters;
public function __construct(array $greeters = [])
{
$this->greeters = $greeters;
}
public function greet($name)
{
foreach ($this->greeters as $greeter) {
$greeter->greet($name);
}
}
}What do you think? ;-)
I would rather use the design above, responsibilities are kept separately then.
P.S.: GreeterCollection should have a design of iterator, but I didn't focus on that.