In the traditional process-oriented languages are often filled with a lot of if/else statements. This situation has easily made the logic of chaos and trouble to amend. The strategy design pattern was borned to solve this kind of problems.
When we face a problem which got serveral solution strategies, we can use the strategy pattern. Its main idea is to provide a unified and fixed interface for all strategy subclasses, for example, a parent class. And then we just use this interface to define each strategy we want.
Now let’s take a look at how Zend_Application_Resource_Resource implements the strategy pattern.
The following are simplified source code and first of all, is a unified interface :
[codesyntax lang=”php”]
<?php
/**
* bootstrap resources : unified interface
*/
interface Zend_Application_Resource_Resource
{
// Constructor
public function __construct($options = null);
// Other functions
public function setBootstrap(Zend_Application_Bootstrap_Bootstrapper $bootstrap);
public function getBootstrap();
public function setOptions(array $options);
public function getOptions();
/**
* Strategy pattern : init() method
* @return mixed
*/
public function init();
}
[/codesyntax]
Then the parent Zend_Application_Resource_ResourceAbstract :
[codesyntax lang=”php”]
<?php
/**
* @see Zend_Application_Resource_Resource
*/
require_once 'Zend/Application/Resource/Resource.php';
/**
* Parent : Resource
* @uses Zend_Application_Resource_Resource
*/
abstract class Zend_Application_Resource_ResourceAbstract implements Zend_Application_Resource_Resource
{
// Implements interface methods
public function __construct($options = null)
{
// ......
}
public function setOptions(array $options)
{
//......
return $this;
}
public function getOptions()
{
// ......
}
public function setBootstrap(Zend_Application_Bootstrap_Bootstrapper $bootstrap)
{
// ......
return $this;
}
public function getBootstrap()
{
// ......
}
// ......
// init() is left for subclasses to implement
}
[/codesyntax]
We haven’t implemented the init() function within parent, but also because the parent is defined as abstract, we can only to subclass for the realization of its init() function. In this case we can make the use of resources properly. Here are two examples about the Layout and the View.
Zend_Application_Resource_Layout :
[codesyntax lang=”php”]
<?php
/**
* Layout resource : Zend_Application_Resource_Layout
* @uses Zend_Application_Resource_ResourceAbstract
*/
class Zend_Application_Resource_Layout
extends Zend_Application_Resource_ResourceAbstract
{
// @var Zend_Layout
protected $_layout;
/**
* Defined in Zend_Application_Resource_Resource
* @return Zend_Layout
*/
public function init()
{
$this->getBootstrap()->bootstrap('FrontController');
return $this->getLayout();
}
/**
* Get the layout object
* @return Zend_Layout
*/
public function getLayout()
{
if (null === $this->_layout) {
$this->_layout = Zend_Layout::startMvc($this->getOptions());
}
return $this->_layout;
}
}
[/codesyntax]
Zend_Application_Resource_View :
[codesyntax lang=”php”]
<?php
/**
* View resource : Zend_Application_Resource_View
* @uses Zend_Application_Resource_ResourceAbstract
*/
class Zend_Application_Resource_View
extends Zend_Application_Resource_ResourceAbstract
{
// @var Zend_View_Interface
protected $_view;
/**
* Defined in Zend_Application_Resource_Resource
* @return Zend_View
*/
public function init()
{
$view = $this->getView();
$viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer();
$viewRenderer->setView($view);
Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
return $view;
}
/**
* Get the view object
* @return Zend_View
*/
public function getView()
{
if (null === $this->_view) {
$this->_view = new Zend_View($this->getOptions());
}
return $this->_view;
}
}
[/codesyntax]
It’s Zend_Application_Bootstrap_Bootstrap who make the really call of init(). It is responsible to collect all the resources and the implementation of their initialization function init() :
[codesyntax lang=”php”]
<?php
/**
* Zend_Application_Bootstrap_Bootstrap::_executeResource($resource)
* Execute one resource
*/
protected function _executeResource($resource)
{
// ......
if ($this->hasPluginResource($resource)) {
// ......
$plugin = $this->getPluginResource($resource);
$return = $plugin->init();
// ......
}
}
[/codesyntax]
This is how Zend_Application_Bootstrap_Bootstrap use resouces and the solution of resources initialization. At the same time, we can create our own resouces very easily through the common interface provided by Zend_Application_Resource_ResourceAbstract.
In fact, large-scale use of strategy pattern has been found in Zend Framework including : Zend_Controller_Action_Helper, Zend_View_Helper, Zend_Filter etc.