我正在MATLAB中编写一个中型分析程序(5-10kloc)(不是我的决定),我正在尝试使用依赖注入来使我的代码更易于测试。我想我理解基本的对象/构造函数注入模型,但我对如何扩展依赖图感到困惑。
例如,如果我有一个对象A,它有一个对象B,它有一个对象C,而对象C有一个需要注入的依赖项,我是否需要将它传递给整个链?最后,由于这是一个数据分析程序,所有内容基本上都会返回到一个AnalyzeData对象/方法,这是否意味着该对象必须注入整个程序的所有依赖项?
也许答案只是在这种情况下使用ServiceFactory / ServiceProvider,但我想知道是否可以将许多依赖项扩展到没有框架的大对象图。
此外,鼓励对我的思维/措辞/基础进行更正 - 我基本上通过Google / HN / SO了解了大部分内容。
答案 0 :(得分:5)
Matlab不可知的答案:
如果(A需要B)和(B需要C)那么你首先创建C,然后创建B并将C传递给B.然后你创建A并传递(B有C)到A。
现在,如果C需要注入依赖项,将其称为D,您仍然可以使用setter注入在此事件序列之后执行此操作。如果依赖项对于C是可选的,则会出现这种情况。否则,在传递给B之前,C未在D 中注入时,可能是程序初始化中的一个缺陷。
如果你想使用构造函数注入在已经拥有(A有(B有C))之后将D注入C,那么你将不得不使用setter注入将新的(C有D)传递给B,但是这一系列事件通常不是DI的有效方案。
答案 1 :(得分:2)
滚动您自己的IoC容器,您可以在其中询问您的依赖项而无需注入它们,或使用静态网关模式获取单例以使用工厂动态创建类。
我发现此视频对这些主题非常有用 - http://www.dnrtv.com/default.aspx?showNum=126
答案 2 :(得分:2)
如果您手动执行依赖注入,最好不要通过依赖项。您只需创建具有其依赖关系的C,使用C创建B,使用B创建A.不需要A知道关于C或其依赖关系的任何信息。它只知道B的接口,通常依赖关系不是对象接口的一部分。
答案 3 :(得分:2)
免责声明:OO语言无关的答案
不,您不需要通过整个对象图传递依赖项。不必实例化具体类型或将它们作为参数传递就是DI的要点。通常,您将有一些其他实体,例如,称为Assembler,它将注入这些依赖项。汇编程序可以是ad-hock,手写或可以是一些DI框架。
例如:
您的汇编程序将引导应用程序并且:
您的所有域对象都只知道接口。汇编程序知道所有对象,但其目的只是创建对象图并将所有内容都放在运动中。手写汇编程序非常合适;有些人喜欢编写接线代码而不是使用配置文件。如果你不打算多次使用它,不要认为编写汇编程序(DI框架)是不值得的。关键是你的课程是用DI方式写的。
看看这篇文章: http://books.google.com/books?id=vRxAnRb3mb4C&pg=PP1&dq=Danijel+Arsenovski#PPA428,M1
答案 4 :(得分:2)
如果我正确理解您的问题,答案可能取决于您如何创建实例化对象的类。在最新版本的MATLAB中,类可以用两种方式定义:“值”类或“句柄”类(MATLAB文档here)。引自文档:
值类:“值类的对象与它们所分配的变量永久关联。复制值对象时,还会复制对象的数据并复制新对象与原始对象的更改无关。实例的行为类似于标准的MATLAB数字和结构类。“
句柄类:“句柄类的对象使用句柄来引用类的对象。句柄是标识类的特定实例的变量。当句柄对象是复制后,会复制句柄,但不会复制存储在对象属性中的数据。副本引用与原始数据相同的数据 - 如果更改原始对象的属性值,则复制的对象会反映相同的更改。“ p>
下面的示例代码给出了一些示例,说明如何与上面描述的“嵌套”对象进行交互,包括值类嵌套对象和句柄类嵌套对象:
% For value classes:
objC = C(...); % Make an object of class C, where "..." stands
% for any input arguments
objB = B(...,objC); % Make an object of class B, passing it objC
% and placing objC in field 'objC'
objA = A(...,objB); % Make an object of class A, passing it objB
% and placing objB in field 'objB'
% If the '.' operator (field access) is defined for the objects:
objA.objB.objC.D = 1; % Set field 'D' in objC to 1
objA.objB.objC = foo(objA.objB.objC,...); % Apply a method that
% modifies objC and
% returns the new
% object
% For handle classes:
hC = C(...); % Get a handle (reference) for a new object of class C
hB = B(...,hC); % Get a handle for a new object of class B,
% passing it handle hC and placing it in field 'hC'
hA = A(...,hB); % Get a handle for a new object of class A,
% passing it handle hB and placing it in field 'hB'
% If the '.' operator (field access) is defined for the objects:
hC.D = 1; % Set field 'D' to 1 for object referenced by hC; Note
% that hC and hA.hB.hC both point to same object, and
% can thus be used interchangably
foo(hC); % Apply a method that modifies the object referenced by hC
% If instead using get/set methods for the handle object:
set(hC,'D',1);
set(get(get(hA,'hB'),'hC'),'D',1); % If variable hC wasn't made, get
% reference from nested objects
foo(hC);
foo(get(get(hA,'hB'),'hC'));
正如您所看到的,使用句柄类可以帮助您避免必须通过将句柄的副本(实际上是指针)存储在另一个变量中来链接函数调用和字段引用。句柄类也不需要使用对这些对象进行操作的方法返回的新副本来覆盖旧的对象副本。
希望这有助于你所要求的。
答案 5 :(得分:0)
不知道关于Matlab的事情,但我假设(从你的话说)有物体。如果是这样,请转到Service Locator而不是依赖注入。服务定位器实现起来非常简单,因此不需要框架。