首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在策略模式中设置策略

在策略模式中设置策略
EN

Stack Overflow用户
提问于 2015-04-26 08:39:17
回答 1查看 406关注 0票数 2

我可能做错了,因为我无法确定在执行战略模式时使用哪种策略的可靠方法。我不太喜欢“静态”地写,也许还有另外一种方法。

背景:,我已经完成了两个(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行的某个函数中。

控制器的外观示例:

代码语言:javascript
复制
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);
    }
}

代码已经被缩短了一点,因为有更多的功能,但并不重要。

接口两个运输提供程序模型正在实现

代码语言:javascript
复制
interface Output
{
    /* Requests delivery information for the specified tracking number */
    public function getDeliveryInformation($number);

    /**
    * Returns acceptor name
    * @return string
    */
    public function getAcceptorName();
}

服务类处理来自运输模型的请求数据

代码语言:javascript
复制
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;
    }
}

传送类的示例;在本例中有两个

代码语言:javascript
复制
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;
    }
}

控制器

代码语言:javascript
复制
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);
        }
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-04-26 09:06:01

您可以使用开关或某种字符串连接来返回所需的策略类。

使用策略模式,在运行时选择正确的策略通常是通过StrategyContext模式:patterns/strategy/php完成的。这允许您隔离算法来选择正确的策略,这样它就不会“在类中200行的某个函数中”。

至于设置运行时策略的算法,我个人喜欢类常量,而不是字符串操作等等。既然游戏的目的是找到一个类名来实例化,为什么不只是一个类常量来返回类名呢?

代码语言:javascript
复制
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;
    }
}

轻量级和易于维护的策略类列表位于一个地方。

当然,您可以使整个事物是静态的,或者使用另一个设计模式,比如抽象的工厂方法来区分相同的东西。真的要看你了。

无论如何,在控制器中,它是一个单线线。

代码语言:javascript
复制
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);
        }
    }
}

当然,您必须修改服务。我还为您的代码修改了上下文类。

代码语言:javascript
复制
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;
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29875495

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档