为什么在Zend Framework 2中使用服务管理器? [英] Why use the Service Manager in Zend Framework 2?

查看:86
本文介绍了为什么在Zend Framework 2中使用服务管理器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我说我有服务:

namespace Helloworld\Service;

class GreetingService
{
    public function getGreeting()
    {
        if(date("H") <= 11)
            return "Good morning, world!";
        else if (date("H") > 11 && date("H") < 17)
            return "Hello, world!";
        else
            return "Good evening, world!";
    }
}

我为此创建了一个发票

public function getServiceConfig()
{
    return array(
        'invokables' => array(
            'greetingService'
                => 'Helloworld\Service\GreetingService'
        )
    );
}

然后在我的控制器中我可以做到:

then in my controller i could do:

public function indexAction()
{
    $greetingSrv = $this->getServiceLocator()
        ->get('greetingService');

    return new ViewModel(
        array('greeting' => $greetingSrv->getGreeting())
    );
}

应该使控制器依赖于服务(和ServiceManager)

supposedly this make the controller dependent of the service (and the ServiceManager)

更好的解决方案是为该服务创建工厂或在ServiceManager中返回闭包并在控制器中创建设置器:

and the better solution is to create factory for that service or return a closure in the ServiceManager and create a setter in the controller:

class IndexController extends AbstractActionController
{
    private $greetingService;

    public function indexAction()
    {

        return new ViewModel(
            array(
                'greeting' => $this->greetingService->getGreeting()
            )
        );
    }

    public function setGreetingService($service)
    {
        $this->greetingService = $service;
    }
}

'controllers' => array(
    'factories' => array(
        'Helloworld\Controller\Index' => function($serviceLocator) {
            $ctr = new Helloworld\Controller\IndexController();

            $ctr->setGreetingService(
                $serviceLocator->getServiceLocator()
                    ->get('greetingService')
            );

            return $ctr;
        }
    )
)

我的问题是为什么?为什么第二种方法比第一种更好?和controller is dependent of the service是什么意思?

My question is why? Why is the second approach better than the first one? and What does it mean that the controller is dependent of the service?

谢谢

推荐答案

默认情况下,ServiceManager被注入到任何ZF2控制器中,因为它扩展了实现ServiceLocatorAwareInterface接口的AbstractController.

The ServiceManager is by default injected within any ZF2 controller, as it extends the AbstractController implementing the ServiceLocatorAwareInterface interface.

第二种方法的形式为"冗余",因为除了已经可以访问之外到ServiceManager实例,每当需要在控制器之间共享服务时,就需要为每个控制器配置注入机制.由于您的控制器已经具有与ServiceManager的依赖关系,因此使用第一种方法并将与域相关的服务注册到ServiceManager会更有意义,从而集中了对Service层的访问.

The second approach has a form of "redundancy" because, besides having already access to a ServiceManager instance, whenever you need to share your service among your controllers, you need to configure for each one of them the injection mechanism. As your controllers have already a dependency vis-à-vis the ServiceManager, It would make more sense to use the first approach and register your Domain related Services to the ServiceManager, centralizing thus the access to the Service layer.

注意:答案的以下部分可能超出了问题的范围,但其目的是提供原始答案的隐藏"背景.

让我们假设我们正在构建一个复杂的系统,其中低耦合,可重用性和增强了测试能力.我们的系统是多层的,我们构建了直到服务层的所有内容.请注意,到目前为止,我们还没有考虑过"MVC" Web层,甚至没有选择给定的框架.

Let's assume we're building a complex system, within which low-coupling, re-usability & test-ability are promoted. Our system is multi-layered and we built everything until the service layer. Note that until now we did not consider yet the "MVC" web layer or even opt for a given framework.

在我们的服务层中(我将考虑这一层,因为它是问题中提到的那一层),我们假设我们采用了原理,将业务逻辑与对象图构造(或依赖关系解析)分开.因此,我们可能有一些通过工厂构造的复杂服务.

Within our Service Layer (I'll consider this layer as it is the one mentioned in the question), we assume that we adopted the principle of separation between the Business Logic and the Object Graph construction (or dependency resolution). So we have probably a couple of complex services that are constructed through factories.

现在,我们的服务层已构建,我们决定将其插入" ZF2之上.当然,正如您的问题所表明的那样,应该可以从控制器访问我们的服务,我们不仅有其他方法可以这样做.但是,我们要避免冗余并利用我们已经构建的内容.假设以下工厂:

Now that our service layer is built, we decide to "plug" it above ZF2. Naturally, Our services should be accessible from the controllers, as your question illustrated it, we have more than a way for doing it. However, we want to avoid redundancy and leverage what we've already built. Let's assume the following factory :

//The following class is a part of our Service layer
public class ComplexServiceFactory{

    private dependencyA;
    private dependencyB;

    public function buildComplexService()
    {
        $service = new ComplexService();
        $service->setDependencyA($this->dependecyA);
        $service->setDependencyB($this->dependecyB);
        return $service;
    }

}

我们现在要做的只是调整(实际上是扩展)我们的工厂,以便它可以被ServiceManager逻辑使用.此类可以视为将系统插入" ZF2的机制的一部分(实际上是 Adapter )

What we'll do now is just to adjust (actually extend) our factory so that it becomes usable by the ServiceManager logic. This class can be considered as part of the mechanism used to "plug" our system to ZF2 (It's actually an Adapter)

public class SMComplexServiceFactory extends ComplexServiceFactory implements
    Zend\ServiceManager\FactoryInterface
{

    public function createService(ServiceLocatorInterface $sm)
    {
        $this->setDependencyA($sm->get('dependecyA'));
        $this->setDependencyB($sm->get('dependecyB'));
        return parent::buildComplexService;
    }

}

这样做,我们不会将对象图构造带到MVC层(否则将是关注点分离和不必要的跨层耦合.从某种意义上说,服务管理器+我们的适应"工厂类是我们的依赖关系解析机制.事实是我们的系统仍然是可移植的,例如我们可以选择另一个系统(另一个框架),并且相对于MVC平台具有较低的依赖性.

By doing so, we're not bringing up the object graph construction to the MVC layer (otherwise it would be a Separation of Concerns violation and an unnecessary cross-layer coupling). The Service Manager + our "Adapted" factories classes are in some sense our dependency resolution mechanism. The fact is that our System is still portable, we could for example opt for another system (another framework) and have a low dependency vis-à-vis the MVC platform.

这篇关于为什么在Zend Framework 2中使用服务管理器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆