繁体   English   中英

Symfony标记服务vs工厂

[英]Symfony Tagged Service vs Factory

我是Symfony2的新手,有点困惑。 抱歉,这个问题听起来很傻。

假设使用带有工厂的服务标记的服务来创建工厂。

根据上述链接中的文档,我可以发现的差异是:

对于标记服务:

您需要编写一个编译器遍历,然后为每个服务定义一个标签。

然后编写一个工厂(任何类。是否应该将其称为工厂?),它将从编译器传递中获取所有带标记的服务的对象。 还要在此处创建一个getter方法,该方法将根据某些条件返回对象。

如果使用工厂创建服务,则只能创建一个服务,并且通过调用静态方法将其对象返回给您。

因此,我想,在加标签的服务中,您可以从许多服务中进行选择,并且如果是按工厂创建服务,则只能创建一个服务。 我认为标记服务已经为工厂服务。 当工厂只能创建一个对象时,为什么需要工厂服务? 可能是我有一个误解,但是标记服务更好,因为编译器遍历在缓存预热时运行,并且标记服务本身存储在那里,因此速度会更快。 但是,服务也被缓存,因此应该没有太大的区别。 但是我不确定这种概念是否正确。

请让我理解两者的概念并使我感到开明。

工厂服务和标记服务具有完全不同的角色。 我将尝试通过示例向您说明一些您可能想使用其中一种的常见情况。

当服务容器中没有构建服务所需的某些参数时,或者在实例化服务之前需要进行一些准备时,通常使用它。 Symfony将自动检查您的服务是否具有自己的工厂,或是否直接根据容器参数构造。

现实世界中的用例

您有处理PayPal付款的服务。 要构建它,您需要在您的PayPal凭据和API端点URL中传递它。

class PayPalPaymentService
{
    // ...

    public function __construct(PayPalCredentials $credentials, $apiEndpoint)
    {
        // ...
    }

    // ...
}

这对您来说效果很好,但是您意识到需要拥有两个环境: LiveSandbox 根据您所处的环境,您的凭据和API终结点URL都不同。

Symfony有两种方法可以为您处理此问题,但其中一种方法是通过工厂服务 :您创建一个工厂,该工厂将根据您当前的本地环境实例化PayPalPaymentService

class PayPalPaymentServiceFactory
{
    const SANDBOX_ENDPOINT = '...';
    const LIVE_ENDPOINT = '...';

    private $livePublic;
    // ...

    public function __construct($livePublic, $liveSecret, $sandboxPublic, $sandboxSecret, $kernelEnvironment)
    {
        $this->livePublic = $livePublic;
        // ...
    }

    public function create()
    {
        if ('prod' === $kernelEnvironment) {
            $credentials = new PayPalCredentials($this->livePublic, $this->liveSecret);
        } else {
            $credentials = new PayPalCredentials($this->sandboxPublic, $this->sandboxSecret);
        }
        $url = 'prod' === $kernelEnvironment ? self::LIVE_ENDPOINT : self::SANDBOX_ENDPOINT;

        return new PayPalPaymentService($credentials, $url);
    }
}

现在,无论何时注入PayPalPaymentService,容器都会首先要求PayPalPaymentServiceFactory创建它,然后注入它。

标记服务

这些是完全不同的故事。 标记服务在整个Symfony代码库中使用:用于FormType,Twig扩展,验证器等。标记服务的概念是一种非常强大的扩展机制。 它允许您将服务标记为用于特定目的的服务。 就像我说的那样,Symfony代码库中已经有它们的示例,但是下面是一个非常简化的示例,以了解您可以使用它们做什么:

您在电子商店中有付款,并且有受支持的付款处理者列表。 每个付款处理方都有其自己的结帐页面。 因此,您决定使其模块化,并让其他人为其创建新的付款处理程序。

在购物车页面上,您需要显示指向所有可用的付款处理程序结帐页面的链接,为此,您需要提供一项服务,该服务为您提供所有可用的结帐链接:

class CheckoutLinksProvider
{
    /**
     * @var ProcessorAdapter[]
     */
    private $adapters;

    public function registerProcessor(ProcessorAdapter $adapter)
    {
        $this->adapters = $adapter;
    }

    public function getCheckoutLinks()
    {
        $links = [];
        foreach ($this->adapters as $adapter) {
            $links[] = $adapter->getCheckoutLink();
        }
        return $links;
    }
}

interface ProcessorAdapter
{
    /**
     * @return string Checkout URL link
     */
    public function getCheckoutLink();

    // ...
}

现在,任何人都可以实现ProcessorAdapter并将其作为捆绑包在Github上共享! 他们要做的只是用您确定的标记来标记ProcessorAdapter实现,例如:“ my_eshop_processor_adapter”。

现在,在您的核心E-shop系统编译器传递中,您可以选择所有ProcessorAdapter实现并将其注册到CheckoutLinksProvider服务中。 瞧! 您有一个完全模块化的付款系统! 任何人都可以创建对自定义处理器的支持,您只需下载其捆绑包并将其注册到内核中,就会出现结帐链接!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM