The behavioral pattern we will discuss today is the Command one, a mechanism for encapsulation of a generic operation.
If you are familiar with C or Php, you have probably already encountered Command as its procedural equivalent: the callback, which is usually implemented as a function pointer or a data structure such as a string or an array in php.
Command is an abstraction over a method call, which becomes a first-class object with all the benefits of object orientation over a set of routines: composition, inheritance and handling.
For example, the GoF book
Note that php 5.3 functional programming capabilities (Closures) can be used as a native implementation of the Command pattern. Though, there is an advantage in type safety in using an abstract data type for every Command hierarchy.
Participants:
- Command: defines an abstraction over a method call.
- ConcreteCommand: implementation of an operation.
- Invoker: refers to Command instances as its available operations.
<?php /** * The Command abstraction. * In this case the implementation must return a result, * sometimes it only has side effects. */ interface Validator { /** * The method could have any parameters. * @param mixed * @return boolean */ public function isValid($value); } /** * ConcreteCommand. */ class MoreThanZeroValidator implements Validator { public function isValid($value) { return $value > 0; } } /** * ConcreteCommand. */ class EvenValidator implements Validator { public function isValid($value) { return $value % 2 == 0; } } /** * The Invoker. An implementation could store more than one * Validator if needed. */ class ArrayProcessor { protected $_rule; public function __construct (Validator $rule) { $this->_rule = $rule; } public function process(array $numbers) { foreach ($numbers as $n) { if ($this->_rule->IsValid($n)) { echo $n, "\n"; } } } } // Client code $processor = new ArrayProcessor(new EvenValidator()); $processor->process(array(1, 20, 18, 5, 0, 31, 42));Some implementation notes for this pattern:
- some of the parameters for the method call can be provided at the construction of the ConcreteCommand, effectively currying the original method.
- A Command can be considered as a very simple Strategy, with only one method, and the emphasis put on the operation as an object you can pass around.
- ConcreteCommands also compose every resource they need to achieve their goal, primarily the Receiver of the action where they call method to execute a Command.
- Composite, Decorator and other patterns can be mixed with the Command one, obtaining multiple Commands, decorated Commands and so on.
No comments:
Post a Comment