Establishing a formatting strategy: defining a contextual class - PHP
The strategy design pattern can be very useful in the context of form validation. This article, the first of two parts, will introduce you to the strategy pattern and give you some idea of how you can use it in your own PHP applications.
Since I’m using object-based programming with PHP 5, the creation of a context where the strategy pattern can be applied will be performed by a single contextual class. However, if you’re working with a procedural approach, creating the aforementioned context should be as simple as defining some functions tasked with implementing a predefined strategy.
Having said that, let me show you the signature for this new contextual class, which I called "StrategySelector." It looks like this:
// define 'StrategySelector' class class StrategySelector{ private $strategy=NULL; public function __construct($strategy){ if($strategy!='html'&&$strategy!='xml'){ throw new Exception('Invalid value for strategy!'); } if($strategy=='html'){ $this->strategy=new StrategyHTML(); } else{ $this->strategy=new StrategyXML(); } } public function displayFileContents(FileDataHandler $dataFileHandler){ return $this->strategy->displayFileContents ($dataFileHandler); } }
Even when the definition of the above contextual class is rather short, it indeed tells a lot about how the strategy pattern works. As you can see, the previous "StrategySelector" class takes up a $strategy" parameter via the corresponding constructor, and according to the value of this argument, that is "html" or "xml," it creates the correct "strategy" object. This object will be used for formatting contents fetched by the file data handler that was shown in the previous section.
So, summarizing, on one hand I created a class that defines the context where different formatting strategies will be applied, while on the other hand, there’s a couple of objects that implement these strategies. Are you starting to grasp the logic that stands behind the strategy pattern? I bet you are!
But now, let me go straight to the point and show you the signatures that correspond to the pair of strategy classes that were shown previously, that is "StrategyHTML" and "StrategyXML." The respective definitions for these new classes are as follows:
// define 'StrategyHTML' class class StrategyHTML{ // return contents of data file as HTML public function displayFileContents(FileDataHandler $dataFileHandler){ return '<div><h2>Contents of data file, formatted as HTML are as follows</h2><p>'.$dataFileHandler->readData().'</p></div>'; } } // define 'StrategyXML' class class StrategyXML{ // return contents of data file as XML public function displayFileContents(FileDataHandler $dataFileHandler){ return '<?xml version="1.0" encoding="iso-8859-1"?> <data><filedata>'.$dataFileHandler->readData(). '</filedata></data>'; } }
As shown above, the two previous strategy classes expose the same "displayFileContents()" method, although obviously they offer different implementations. In the first case, contents fetched via the file data handler class will be outputted as HTML, while in the second case, the same contents will be formatted as XML.
At this point, I’m pretty certain that you’ve already learned how the strategy pattern works in this situation, where the pattern is applied to format data fetched from a remote file.
However, there is still a missing piece in the previous scenario, since you haven’t yet seen how the strategy selector and the respective strategy classes can be put to work in conjunction. Therefore, keeping in mind this situation, in the section to come I’m going to show you an illustrative example where all prior classes are going to be used together.
Want to see how this educational example will be developed? Go ahead and read the next few lines. I’ll be there, waiting for you.