I have been working on a library, which implements command dispatcher (or invoker), part of command pattern. One possible use of command pattern is to encapsulate business logic into separate classes, that communicate to developers/stakeholders the intent of the code and effectively hide the implementation details.
Sample use scenario
Let's say we have a controller, that handles de-serializing POSTed JSON into a model, that can be persisted with ORM. Controller action logic for that might look something like this:
$user = $serializer->deserialize('User', $json);
$user->setCreator($loggedInUser);
// ...some other pre-persist stuff
$orm->persist($user);
$orm->flush();
$emailService->sendPasswordCreationLink($user);
With Command Dispatcher, we encapsulate logic away into command classes:
$user = $dispatcher->handle(CreateUserCommand::create(array($json, $loggedInUser)));
$dispatcher->handleCommands(array(
SaveUserCommand::create(array(($orm, $user)),
EmailUserPasswordCreationLinkCommand::create(array($emailService, $user))
));
The latter code communicates itself considerably better, even non-developers can understand the program flow and inspect it's validity. We are now using the domain language to express the program flow.
Utilizing the dispatcher
One advantage of using a dispatcher is that it provides central place for handling pre- and post-execution logic. Let's say we also want to log our program flow for record keeping. We add a pre-command handler, which adds a log record before calling command's execute() -method:
$dispatcher->addPreCommandHandler(function($command) use ($logger) {
$command->log($logger);
});
Now each command needs to implement log() -method.
class SampleCommand extends AbstractCommand implements CommandInterface
{
// ...
public function log($logger)
{
$logger->info('Executing Sample command...');
}
}
Other uses for dispatcher could be queuing commands, storing execution history, adding undo logic for commands etc.