- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
公共(public)服务更新:
自从我最初提出这个问题以来,我学到了很多东西。如果您正在阅读本文,请采纳我的建议并完全避免使用 static
。只是。不。采用。它。 没有办法进行依赖注入(inject);依赖注入(inject)就是这种方式。
我最近花了很多时间研究各种控制反转 (IOC) 概念。我完全同意那些认为 Service Locator 是一种反模式的人。我构建了一个修补程序,并且对它允许使用静态定位器方法在类中间导入“全局”实体以及隐藏对象的实际依赖项的可能性的能力感到震惊。
从服务定位器开始,我着手创建一个依赖注入(inject) (DI) 容器,它为我提供了静态依赖访问的灵 active ,而没有静态变量的伴随缺点。
下面是此类实现的一个简单示例:
<?php
class Container
{
protected static $params = [];
public function store($key, $val)
{
static::$params[$key] = $val;
return $this;
}
public function fetch($key)
{
if (isset(static::$params[$key])) {
return static::$params[$key];
}
$msg = "No parameter match found in container: $key";
throw new OutOfBoundsException($msg);
}
}
$container = new Container;
$container->store('widgetDep', new WidgetDependency);
$container->store('kumquatDep', new KumquatDependency);
// and somewhere else in the application without access to the global namespace
// (i.e. the $container instance we just created) ...
$widget = new Widget(new Container);
$kumquat = new Kumquat(new Container);
这似乎是朝着正确方向迈出的一步,因为静态 $params
属性受到保护,并且不存在可在“全局”静态范围内访问或操作它的静态方法:对象需要访问访问依赖项的容器。
不幸的是,在这个容器中存储依赖关系意味着现在每个注入(inject)依赖关系的对象都有一个对容器对象的虚假依赖关系,从而隐藏了它的真实依赖关系。另一个负面影响副作用是每个对象都可以访问容器中每个可用的依赖项,显然,Widget 对象不应该访问 Kumquat 对象的依赖项.此外,通过这种方法使用抽象工厂只会将伪造的依赖项从 Widget 和 Kumquat 类移到工厂中。
借助 5.4 的新对象构造取消引用功能,我们可以执行以下操作,而无需访问全局命名空间中已创建的 $container
实例:
$widget = new Widget((new Container)->fetch('widgetDep'));
$kumquat = new Kumquat((new Container)->fetch('kumquatDep'));
使用这种方法我们已经成功:
现在,一个可能的缺点是这种方法意味着开发人员必须遵守足够的纪律,不能将完整的 Container
对象作为依赖项传递。这是至关重要的。
分两部分:
Container::$params
是否必要?它是否应该是一个标准的 protected 属性,由全局命名空间中的顶级对象图工厂类/方法访问(避免需要 static
)?最佳答案
你根本不应该在这里使用static
。只需创建一个容器:$container = new DIContainer();
并将该对象用作典型的依赖项。毕竟在应用程序的核心中只有极少数地方需要访问整个容器。
看看Symfony's Dependency Injection component - 一段相当不错的代码。
根据第一条评论。是的,你误会我了。通常你只需要容器中的几个依赖项,所以你会这样写:
$service = new Service($container->get('dep.a'), $container->get('dep.b'), 123);
我的观点是你不应该在容器中使用静态属性,因为它只是一个全局对象。之间没有区别:
global $container;
$widget = new Widget($container->fetch('widgetDep'));
$kumquat = new Kumquat($container->fetch('kumquatDep'));
$widget = new Widget(Container::getInstance()->fetch('widgetDep'));
$kumquat = new Kumquat(Container::getInstance()->fetch('kumquatDep'));
// You're using new objects but they share the same, **global** array.
// Therefore, they are actually global themselves.
$widget = new Widget((new Container())->fetch('widgetDep'));
$kumquat = new Kumquat((new Container())->fetch('kumquatDep'));
换句话说,容器本身应该是一个局部变量,如果您需要在其他地方访问它(某些对象可能需要访问整个容器),那么您应该明确地将它作为该对象的依赖项传递。
正如我之前所说,看看 Symfony DIC 和整个框架,看看如何制作一个好的、编写良好的 DIC。
简单容器:
class Container {
private $services = array();
public function get($service) {
if (!array_key_exists($this->services, $service)) {
throw ...;
}
return $this->services[$service];
}
}
$containerA = new Container();
$containerB = new Container();
// $containerA and $containerB are completely different
// objects and don't share anything
关于php - PHP 5.4 对象取消引用是否成功缓解了此 DI 容器中静态存储参数的缺点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9179586/
我正在使用 jQuery 的 $.ajax 函数来提交表单,它可以工作,但成功正是我遇到问题的地方。这是我的代码: $("#form").submit(function () { $.
我正在使用动态分页。 我需要在开始另一个事件之前取消 jQuery ajax 中的 success 事件。 我已经设置了一个等于$.ajax()的变量,在这样做之前,无论如何我都会调用abort。 问
如果我错了,请纠正我,但我对 $.post 成功/失败的理解是,如果 url 有效,这将返回成功。唯一会返回失败的情况是 url 无效。 如果这是真的,我如何验证成功函数?我问的原因是无论发生什么,即
HANDLE hFile = CreateFile(LPCTSTR("filename"), // name of the write
我正在使用以下代码发送短信。但这似乎不会在未发送短信时产生异常。例如,当没有足够的钱发送时,我仍然会去 smsSucces();有没有人知道解决此问题的方法以确保它已发送? private b
我正在尝试将字符串转换为 DateTime,在一台计算机上,它工作正常,但在另一台计算机上,它却不行!它运行的计算机运行的是 32 位 Windows 7,它不运行的计算机运行的是 64 位 Wind
我在页面上使用表单让用户输入将用于各种目的的图像的 url。我正在编写一个 ajax 方法来确定他们提供的 url 是否实际上是图像。到目前为止,我已经这样做了: $(document).on('re
我在 jquery 中对 php 脚本进行 ajax 调用。但是 php 脚本需要返回什么才能触发 ajax 中的成功/错误处理程序。所以这是 ajax: $.ajax({ data:
几个简单的问题: 对于 native 和 Flash/Silverlight 垫片来说,成功事件是“规范化”事件吗?记录的示例表明它仅适用于 Flash/Silverlight 对象准备就绪的情况。
这个问题不太可能对任何 future 的访客有帮助;它只与一个小的地理区域、一个特定的时间点或一个非常狭窄的情况相关,通常不适用于互联网的全局受众。如需帮助使这个问题更广泛适用,visit the h
我尝试使用新的 Groovy Grape Groovy 1.6-beta-2 中的功能,但我收到一条错误消息; unable to resolve class com.jidesoft.swing.J
我正在使用 sequelize/nodejs/express/react 将实体持久化到 postgres 数据库 我有两个主要模型,国家和事件,我正在使用该应用程序,并且有一个名为“保存到数据库”的
我有以下代码,其中有 2 个电子邮件输入字段,我需要验证它们是否相同,并且使用 jQuery validate equalTo 成功运行。 Email Address
我正在尝试找出解决此问题的正确方法。 假设我们有一家元素商店。这些项目可以编辑、删除和创建。编辑或添加项目时,路线更改为/item/add 或/item/edit/{id}。 在 saga 成功添加或
这个问题已经有答案了: How do I return the response from an asynchronous call? (42 个回答) 已关闭 8 年前。 我有这段代码,警报工作正常
Closed. This question needs to be more focused。它当前不接受答案。 想改善这个问题吗?更新问题,使其仅关注editing this post的一个问题。
我想在单击超链接 (.remove_resort) 时(成功的 ajax 调用后)删除超链接的(父)跨度。 虽然ajax调用成功,但是最后span并没有被移除。这里出了什么问题? 请记住:有几个类
我正在编写一个非常简单的程序来将鼠标剪辑到指定的窗口。它从系统托盘运行,没有可见窗口。由于同一窗口会有多个实例,因此它使用 EnumWindows() 迭代每个顶级窗口,并将它们的 hwnd 与 Ge
我正在尝试找出如何执行 if 语句,以便如果玩家的击球率超过 0.250,则会为成功的 tr 添加一个类别。 我发现了以下堆栈问题,但我不确定可以使用或应该使用哪种方式以及如何使用这些堆栈问题。 ht
我是 Prolog 的新手,我正在尝试解决这个练习: Define a predicate greater_than/2 that takes two numerals in the notation
我是一名优秀的程序员,十分优秀!