我可能做错了,因为我无法确定在执行战略模式时使用哪种策略的可靠方法。我不太喜欢“静态”地写,也许还有另外一种方法。
背景:,我已经完成了两个(2)实现(soap + http)来传送提供者,以便为用户输入的任何前端检索跟踪和跟踪信息。它们都遵循一个接口,这样我就知道哪些函数是可用的,哪些函数应该可用(PHP :3)。我缩短了下面的类名,因为这是Magento,类名非常长。
流:客户在表单中输入跟踪号码并提交。请求发送给控制器,控制器初始化Service类的一个实例,通过。$ service ->setOutput(' tracking/service_gls ') --注意tracking/service_gls只是直接映射到服务类(Magento ),$ $service->getDeliveryInformation($number)被调用(我们知道这是因为接口而存在的),整个$service对象返回到视图并显示数据。
我的挑战:,我使用一个开关大小写来设置tracking/service_gls和tracking/service_服务,然后调用getDeliveryInformation()。这是正确的做法吗?我觉得如果有人想要连接另一个运输供应商,这是有点太静态和难以维护。他们必须输入控制器并手动将另一个条目添加到开关情况中,在类中的200行的某个函数中。
控制器的外观示例:
public function getDeliveryInformationAction()
{
$id = $this->getRequest()->getParam('id', false);
if ($id && $this->getRequest()->isAjax())
{
// SO note: service parameter is just two radio buttons with values "gls", "otherservice"
$serviceType = $this->getRequest()->getParam('service', false);
try
{
// SO note: same as doing new Class()
$service = Mage::getModel('tracking/service');
switch ($serviceType)
{
case 'gls':
$service->setOutput('tracking/service_gls');
break;
case 'other':
$service->setOutput('tracking/service_other');
break;
}
$shipment = $service->getDeliveryInformation($id);
$output = // .. create block that contains the view, $output will contain the shipment data; this is returned to the ajax request.
}
catch (Exception_RequestError $e)
{
..
}
// finally
$this->getResponse()->setHeader('content-type', 'text/html', true);
$this->getResponse()->setBody($output);
}
}代码已经被缩短了一点,因为有更多的功能,但并不重要。
接口两个运输提供程序模型正在实现
interface Output
{
/* Requests delivery information for the specified tracking number */
public function getDeliveryInformation($number);
/**
* Returns acceptor name
* @return string
*/
public function getAcceptorName();
}服务类处理来自运输模型的请求数据
class Service
{
protected $output;
/**
* Sets the output model to use
* @param string $outputType
*/
public function setOutput($outputModel)
{
// SO note: same as doing new Class()
// Magento people note: getModel() works fine tho.. ;-)
$modelInstance = Mage::app()->getConfig()->getModelInstance($outputModel);
$this->output = $modelInstance;
}
/**
* Returns delivery information for the specified tracking number
* @param string $number
* @return instance of output class
*/
public function getDeliveryInformation($number)
{
// SO note: This makes the shipping class request
// information and set data internally on the object
$this->output->getDeliveryInformation($number);
return $this->output;
}
}传送类的示例;在本例中有两个
class Service_Gls implements Output
{
const SERVICE_NAME = 'GLS';
const SERVICE_URL = 'http://www.gls-group.eu/276-I-PORTAL-WEBSERVICE/services/Tracking/wsdl/Tracking.wsdl';
protected $locale = 'da_DK';
/* Class constructor */
public function __construct() { }
/**
* Requests delivery information for the specified tracking number
* @param mixed $number
*/
public function getDeliveryInformation($number)
{
$this->_getDeliveryInformation($number);
}
/**
* Requests and sets information for the specified tracking number
* @param mixed $number
*/
private function _getDeliveryInformation($number)
{
// SO note: Extending from Varien_Object has magic __get, __set .. hence why there is no getData() function in this class.
if (!count($this->getData()))
{
$client = new SoapClient($url);
$client->GetTuDetail($reference));
.. set data
}
}
/**
* Returns acceptor name
* @return string
*/
public function getAcceptorName()
{
$signature = $this->getSignature();
return (isset($signature)) ? $this->getSignature() : false;
}
/**
* Returns the name of the current service
* @return string
*/
public function __toString()
{
return self::SERVICE_NAME;
}
}控制器
class AjaxController extends Mage_Core_Controller_Front_Action
{
public function getDeliveryInformationAction()
{
$id = $this->getRequest()->getParam('id', false);
if ($id && $this->getRequest()->isAjax())
{
// SO note: service parameter is just two radio buttons with values "gls", "otherservice"
$serviceType = $this->getRequest()->getParam('service', false);
try
{
$service = Mage::getModel('tracking/service');
switch ($serviceType)
{
case 'gls':
$service->setOutput('tracking/service_gls');
break;
case 'other':
$service->setOutput('tracking/service_other');
break;
}
$shipment = $service->getDeliveryInformation($id);
$output = // .. create block that contains the view, $output will contain the shipment data; this is returned to the ajax request.
}
catch (Exception_RequestError $e)
{
..
}
// finally
$this->getResponse()->setHeader('content-type', 'text/html', true);
$this->getResponse()->setBody($output);
}
}
}发布于 2015-04-26 09:06:01
您可以使用开关或某种字符串连接来返回所需的策略类。
使用策略模式,在运行时选择正确的策略通常是通过StrategyContext模式:patterns/strategy/php完成的。这允许您隔离算法来选择正确的策略,这样它就不会“在类中200行的某个函数中”。
至于设置运行时策略的算法,我个人喜欢类常量,而不是字符串操作等等。既然游戏的目的是找到一个类名来实例化,为什么不只是一个类常量来返回类名呢?
class OutputStrategyContext{
const SERVICE = 'tracking/service_gls';
const OTHER = 'tracking/service_other';
private $strategy;
public function __construct($serviceType)
{
$strategy = constant('self::' . strtoupper($serviceType));
$modelInstance = Mage::app()->getConfig()->getModelInstance($strategy);
$this->strategy = $modelInstance;
}
public function getStrategy()
{
return $this->strategy;
}
}轻量级和易于维护的策略类列表位于一个地方。
当然,您可以使整个事物是静态的,或者使用另一个设计模式,比如抽象的工厂方法来区分相同的东西。真的要看你了。
无论如何,在控制器中,它是一个单线线。
class AjaxController extends Mage_Core_Controller_Front_Action
{
public function getDeliveryInformationAction()
{
$id = $this->getRequest()->getParam('id', false);
if ($id && $this->getRequest()->isAjax())
{
// SO note: service parameter is just two radio buttons with values "gls", "otherservice"
$serviceType = $this->getRequest()->getParam('service', false);
try
{
$service = Mage::getModel('tracking/service');
$outputModel = new OutputStrategyContext($serviceType)->getStrategy();
$service->setOutput($outputModel);
$shipment = $service->getDeliveryInformation($id);
$output = // .. create block that contains the view, $output will contain the shipment data; this is returned to the ajax request.
}
catch (Exception_RequestError $e)
{
..
}
// finally
$this->getResponse()->setHeader('content-type', 'text/html', true);
$this->getResponse()->setBody($output);
}
}
}当然,您必须修改服务。我还为您的代码修改了上下文类。
class Service
{
protected $output;
/**
* Sets the output model to use
* @param string $outputType
*/
public function setOutput($outputModel)
{
// SO note: same as doing new Class()
// Magento people note: getModel() works fine tho.. ;-)
$this->output = $outputModel;
}
/**
* Returns delivery information for the specified tracking number
* @param string $number
* @return instance of output class
*/
public function getDeliveryInformation($number)
{
// SO note: This makes the shipping class request
// information and set data internally on the object
$this->output->getDeliveryInformation($number);
return $this->output;
}
}https://stackoverflow.com/questions/29875495
复制相似问题