为什么要在 ZF2 上使用服务? [英] Why to use a Service on ZF2?

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

问题描述

我正在尝试了解 ZendFramework 2 的一些原理,如果我可以使用 composer autoloader 加载实例对象,我想知道为什么要在 ZF2 module.config.php 上注入服务.Zend 工厂也是一样,如果我可以轻松实现工厂类并在控制器中调用它,为什么要使用它?

I'm trying to understand some principles of the ZendFramework 2, and I want to know why to inject services on the ZF2 module.config.php if I can load instance a object using composer autoloader. The same thing for zend factories, why to use this if I can easily implement a Factory class and call it in a controller?

推荐答案

首先要明确 - ServiceLocator 不是创建对象的 必须使用 方式.您仍然可以直接创建对象,并且在很多情况下这是一种非常有效的方法.

To be clear up front - the ServiceLocator is not a must use way for creating objects. You still can create objects directly, and in quite a few cases this is a perfectly valid approach.

话虽如此,您想要对某些对象使用 ServiceLocator 的原因有几个.不幸的是,维基百科页面对理解使用服务定位器的原因没有多大帮助.我发现此处的描述和示例更有用.

With that being said, there are a few reasons why you want to use the ServiceLocator for some objects. Unfortunately the Wikipedia Page on this doesn't help much with understanding the reasons to use a service locator. I found the description and examples here much more useful.

对于此的其余部分,我将使用可互换的术语classservice.我将需要服务的类/对象命名为 Consumer,负责创建服务的工厂为 factory.

For the remainder of this, I'll use the terms class and service interchangeable. I'll name the class/object requiring a service Consumer, the factory responsible for creating a service a factory.

关于服务管理器,有一个非常重要的事实需要了解.服务名称不必必须是类名.它可以是任何字符串(例如服务的名称).

There is one very important fact to know about service managers. The service name does not need to be a class name. It can be any string (e.g. the services' name).

您想要使用服务定位器的主要原因是:

The major reasons why you want to use a service locator are:

  • 使用同一个服务实例和多个地方(共享服务)
  • 从消费者那里抽象出服务的方式constructions(它是由工厂创建的还是直接实例化的)
  • 将模块彼此分离
  • 创建抽象服务(由任意字符串标识),并让其他人决定该服务的具体实现
  • 使用委托人扩展服务创建
  • Use the same instance of a service and many places (shared services)
  • Abstract the means of service constructions from the consumer (is it created by a factory or instantiated directly)
  • Decouple modules from each other
  • Create abstract services (identified by any string), and let others decide on the concrete implementation of this service
  • Extend service creation using delegators

重复使用服务

这可能是最容易看到的.通常,您有一项服务并希望在您的应用程序中使用相同的实例.用例可以是从Configuration 服务到缓存服务 的任何内容.

This is probably the easiest to see. Typically you have a service and want the same instance to be used across your application. Use-cases for this could be anything from a Configuration service to Caching Service.

我们当然可以使用单例来确保全局只创建一个实例 - 这也可以.但这并没有提供以下其他参数的好处.

We sure could use a Singleton for making sure that only one instance is created globally - and this would work as well. But this doesn't provide the benefits of the other arguments following.

在 Zf2 中,默认情况下所有服务都是共享的.因此,每次按名称请求服务时,都会获得相同的实例.这可以在每个服务级别上关闭(这是 service_manager 配置中的 shared 配置键).

In Zf2, all services are shared by default. So each time you request a service by name, you will get the same instance. This can be turned of on a per-service level (that's the shared config key for in the service_manager configuration).

抽象的创作手段理想情况下,消费者不需要知道如何创建所需的服务.这使得它与所需的服务更加分离.它需要知道的只是说我需要这个服务的一个实例.

Abstract means of creation Ideally, the consumer should not need to know how a required service is to be created. This makes it more decoupled from the required service. All it needs to know, is to say I require an instance of this service.

使用服务管理器,您可以实现这一点:您要求服务管理器获取特定服务,但您并不关心服务管理器实际如何创建它.可能是服务管理器直接实例化它.可以是工厂.消费者并不关心——它只关心结果,即该服务的一个实例.

Using a service manager, you can achieve this: you ask the service manager to fetch a specific service, But you don't care how the service manager actually creates this. It could be that the service manager instantiates it directly. It could be a factory. The consumer doesn't care - all it only cares about the result, an instance of that service.

这样做的好处是,您可以透明地替换创建该服务的方式,而不必将消费者代码更新为创建该服务的新方式.

The benefit of doing so is that you can replace the mean of creating that service transparently and don't have to update the consumer code to the new way of creating that service.

解耦模块

隐藏服务的创建方式会导致模块解耦.假设您有两个模块 CacheUser.user 模块需要来自 Cache 模块的 Cache 服务.您不必直接依赖 Cache 模块和实现,而是通过名为 cache 的服务隐藏该事实.user 模块根本不关心 Cache 模块如何创建该服务.事实上,我们甚至可以用另一个提供相同服务的模块 AdvancedCache 替换 Cache 模块,而无需更新 User 模块.User 模块与特定模块无关 - 仅存在名为 cache 的服务.

Hiding the way of how a service is created leads to decoupling modules. Let's assume you have two modules Cache and User. The user module requires a Cache Service from the Cache module. Instead of having to rely on the Cache Module and implementation directly, you hide that fact by a service named cache. The user module doesn't care at all how the Cache module creates that service. In fact we could even replace the Cache module with another module AdvancedCache providing the same service, without having to update the User module. The User module isn't tied to a particular module - only the the existence of a service named cache.

抽象服务名称

在前面的例子中,我已经介绍了这个概念.每个服务都有一个全局名称——一个简单的字符串.在许多情况下,这是类名,但我们不仅限于此.

In the previous example, I already introduced this concept. Each service has a global name - a simple string. In many cases that is the class name, but we are not limited to this.

继续前面的 cache 服务示例:在这里我们没有指定 User 模块实际想要哪种类型的缓存 - 它并不关心.它可以是 array(内存中)缓存、file 缓存或 memcache 缓存.

To stick the the previous example of a cache service: in here we didn't specify which type of cache the User Module actually wants - it doesn't care. It could be an array (in-memory) cache, a file cache, or memcache cache.

在其他地方,我们决定要全局使用哪个缓存,并将该具体实现分配给 cache 的名称.所有需要 cache 服务的模块现在都会自动接收该实现而无需更新.

In some other place we decide which cache we want to use globally and assign that concrete implementation to the name of cache. All modules requiring that cache service now automatically receive that implementation without needing to be updated.

在 Zf2 中,这被广泛使用.以 Request 服务为例.在许多情况下,这是 Http\Request 的一个实例.但是当使用 CLI 时,这将是一个 Console\Request.但是在请求 Request 服务时,我们实际上并不关心重新接收到哪个,只要它们的行为相同即可.

In Zf2, this is used quite extensively. Take the Request Service for example. In many cases this is an instance of the Http\Request. But when using the CLI, this would be an Console\Request instead. But when requesting the Request service, we literally don't care about which one re receive, as long as they behave the same.

另一个例子是Renderer.根据我们想要呈现输出的环境,我们会收到不同的实现(HTML/Json/Console 使用).但是我们的消费者不需要知道我们正在为/呈现哪个具体实现.

Another example for this would be the Renderer. Depending on the environment we want to render the output for, we receive a different implementation (HTML/Json/Console usage). But our consumer doesn't need to know which concrete implementation we are rendering for/.

委托人

委托人可以用于扩展一个工厂.尽管这是一个更高级的用例,但我暂时将其排除在外.说了这么多,您可以在创建时扩展/代理服务创建.

Delegators can be used to extend a factory. I'll leave this out of scope for now though as this is a more advanced use-case. So much be said, you can extend/proxy service creations upon creation time.

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

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