- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我将以简短的问题开头作为长问题的开头:
问题的简短版本
允许对象实例化其自己的依赖关系,然后提供构造函数参数(或setter方法)以简单地覆盖默认实例化,这是怎么回事?
class House
{
protected $door;
protected $window;
protected $roof;
public function __construct(IDoor $door = null, IWindow $window = null, IRoof $roof = null)
{
$this->door = ($door) ? $door : new Door;
$this->window = ($window) ? $window : new Window;
$this->roof = ($roof) ? $roof : new Roof;
}
}
#index.php (front controller)
$db = new PDO(...);
$cache = new Cache($dbGateway);
$session = new Session($dbGateway);
$router = new Router;
$router::route('/some/route', function() use ($db, $cache, $session)
{
$controller = new SomeController($db, $cache, $session);
$controller->doSomeAction();
});
#SomeController.php
class SomeController
{
protected $db;
protected $cache;
protected $session;
public function __construct(PDO $db, ICache $cache, ISession $session)
{
$this->db = $db;
$this->cache = $cache;
$this->session = $session;
}
public function doSomeAction()
{
$user = new \Domain\User;
$userData = new \Data\User($this->db);
$user->setName('Derp');
$userData->save($user);
}
}
$this->factory->make('\Data\User');
之类的笨拙实例化新对象似乎也很尴尬。尤其是因为您需要编码抽象工厂类,所以实际工厂将为您想要的对象关联依赖关系。
最佳答案
您的问题问得很好,我非常喜欢人们出于“单元测试和可维护性”的原因质疑常识(无论您是哪个程序员,如果您不这样做,它们都是坏程序员) -it-topics,它总是与单元测试和可维护性有关。因此,您在这里提出了一个正确的问题:DI确实支持单元测试和可维护性吗?并预料到:如果使用正确,它会...
关于分解
依赖注入(inject)(DI)和控制反转(IoC)是机制,它们增强了封装和分离OOP关注点的核心概念。因此,要回答这个问题,就必须争论为什么封装和分离关注点是一件很酷的事情。两者都是分解的核心机制:封装(是的,我们有模块)和关注点分离(并且在某种意义上有模块)。关于这个话题可以写很多东西,但是就目前而言,要说它是关于降低复杂性就足够了。系统的分解使您可以将系统(无论多大)分解为人脑能够管理的部分。尽管有点哲理,但这确实很重要:如果人脑没有局限性,那么整个可维护性主题就不会那么重要。好的,让我们说:分解是一种将系统的感知复杂性降低为我们可以管理的块的技巧。
但是,与往常一样,它要付出代价:分解也增加了复杂性,就像您对DI所说的那样。仍然有意义吗?是的,因为:
人为增加的复杂度与系统的固有复杂度无关。
基本上就是抽象的水平。它的含义是:您需要根据要构建的系统的固有复杂性(或一天可能达到的复杂性)来选择分解的程度和实现该分解所花费的精力。
与DI一起分解
特别是关于DI:根据以上所述,存在足够小的系统,其中DI的增加的复杂性不能证明降低的感知复杂性是合理的。而且,不幸的是,网络上的每个教程都涉及其中之一,这不支持理解整个绒毛的含义。
但是,大多数(或至少许多)现实生活项目都达到了固有的复杂性程度,因此在附加分解上的投资得到了充分的利用,因为降低了感知的复杂性可以加快后续开发的速度并减少错误。依赖注入(inject)是做到这一点的技术之一:
DI支持将What(接口(interface))和How(实现)分开:如果仅关于玻璃门,我同意:如果这对于一个人的大脑来说太多了,那么他(她)可能就不应该成为程序员。但是现实生活中的事情更加复杂:DI使您可以专注于真正重要的事情:作为一所房子,只要我可以依靠它可以关闭和打开的事实,我就不在乎我的门。也许现在没有门了?您现在根本不需要关心。将组件注册到您的容器中时,您可以再次关注:我要在我家中的哪扇门上?您不再需要关心门或房屋本身:它们很好,您已经知道了。您已经将关注点分开了:事物如何组合在一起(组件)以及实际上如何将它们组合在一起(容器)的定义。根据我的经验,仅此而已。听起来很笨拙,但在现实生活中,这是一个了不起的成就。
少一些哲学
为了使它重新 Root ,有许多更实际的优点:
随着系统的发展,总有一些尚未开发的部分。在大多数情况下,指定行为要比实现行为少得多的工作。没有DI,只要没有门被开发就无法开发房屋,因为没有可实例化的东西。使用DI,您无需担心:您只需使用界面设计房屋,就可以针对这些界面使用模拟程序编写测试,并且还可以:您的房屋可以正常工作,甚至不存在 window 和门。
您可能知道以下几点:您已经为某件事工作了几天(让我们说一扇玻璃门),您为此感到自豪。六个月后-在此期间您学到了很多东西-再次查看它,这很废话。你把它扔掉。如果没有DI,则需要更改房屋,因为它使用的是您刚刚废弃的类。有了DI,您的房子就不会改变。它可能位于它自己的程序集中:您甚至不需要重新编译内部程序集,它就不会受到影响。在复杂的情况下,这是一个巨大的优势。
还有更多,但也许考虑到所有这些,当您下次阅读DI的好处时,更容易想象DI的好处...
关于php - 依赖重载而不是依赖注入(inject)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19504781/
我正在尝试测试依赖于其他服务 authService 的服务 documentViewer angular .module('someModule') .service('docu
如果我的网站上线(不要认为它会,目前它只是一个学习练习)。 我一直在使用 mysql_real_escape_string();来自 POST、SERVER 和 GET 的数据。另外,我一直在使用 i
我有以下代码,它容易受到 SQL 注入(inject)的攻击(我认为?): $IDquery = mysqli_query($connection, "SELECT `ID` FROM users W
我一直在自学如何创建扩展,以期将它们用于 CSS 注入(inject)(以及最终以 CSS 为载体的 SVG 注入(inject),但那是以后的问题)。 这是我当前的代码: list .json {
这个简单的代码应该通过 Java Spring 实现一个简单的工厂。然而结果是空指针,因为 Human 对象没有被注入(inject)对象(所以它保持空)。 我做错了什么? 谢谢 配置 @Config
我正在编写一个 ASP.NET MVC4 应用程序,它最终会动态构建一个 SQL SELECT 语句,以便稍后存储和执行。动态 SQL 的结构由用户配置以用户友好的方式确定,具有标准复选框、下拉列表和
首先让我说我是我为确保 SQL 注入(inject)攻击失败而采取的措施的知己。所有 SQL 查询值都是通过事件记录准备语句完成的,所有运算符(如果不是硬编码)都是通过数字白名单系统完成的。这意味着如
这是 SQL 映射声称可注入(inject)的负载: user=-5305' UNION ALL SELECT NULL,CONCAT(0x716b6b7071,0x4f5577454f76734
我正在使用 Kotlin 和 Android 架构组件(ViewModel、LiveData)构建一个新的 Android 应用程序的架构,并且我还使用 Koin 作为我的依赖注入(inject)提供
假设 RequestScope 处于 Activity 状态(使用 cdi-unit 的 @InRequestScope) 给定 package at.joma.stackoverflow.cdi;
我有一个搜索表单,可以在不同的提供商中搜索。 我从拥有一个基本 Controller 开始 public SearchController : Controller { protected r
SQLite 注入 如果您的站点允许用户通过网页输入,并将输入内容插入到 SQLite 数据库中,这个时候您就面临着一个被称为 SQL 注入的安全问题。本章节将向您讲解如何防止这种情况的发生,确保脚
我可以从什么 dll 中获得 Intercept 的扩展?我从 http://github.com/danielmarbach/ninject.extensions.interception 添加了
使用 NInject 解析具有多个构造函数的类似乎不起作用。 public class Class1 : IClass { public Class1(int param) {...} public
我有一个 MetaManager 类: @Injectable() export class MetaManager{ constructor(private handlers:Handler
我是 Angular 的新手,我不太清楚依赖注入(inject)是如何工作的。我的问题是我有依赖于服务 B 的服务 A,但是当我将服务 A 注入(inject)我的测试服务 B 时,服务 B 变得未定
我正在为我的项目使用 android 应用程序启动、刀柄和空间。我在尝试排队工作时遇到错误: com.test E/WM-WorkerFactory: Could not instantiate co
我不确定这是什么糖语法,但让我向您展示问题所在。 def factors num (1..num).select {|n| num % n == 0} end def mutual_factors
简单的问题,我已经看过这个了:Managing imports in Scalaz7 ,但我不知道如何最小化注入(inject) right和 left方法到我的对象中以构造 \/ 的实例. 我确实尝
在我的 Aurelia SPA 中,我有一些我想在不同模块中使用的功能。它依赖于调用时给出的参数和单例的参数。有没有办法创建一个导出函数,我可以将我的 Auth 单例注入(inject)其中,而不必在
我是一名优秀的程序员,十分优秀!