9

我正在 MATLAB 中编写一个中型分析程序(5-10kloc)(不是我的决定),并且我正在尝试使用依赖注入来使我的代码更具可测试性。我想我了解基本的对象/构造函数注入模型,但我对这如何扩大依赖关系图感到困惑。

例如,如果我有对象 A,它有一个对象 B,它有一个对象 C,并且对象 C 有一个需要注入的依赖项,我是否需要通过整个链传递它?最终,由于这是一个数据分析程序,一切基本上都回到了一个 AnalyzeData 对象/方法,这是否意味着该对象必须注入整个程序的所有依赖项?

也许答案只是在这种情况下使用 ServiceFactory/ServiceProvider,但我想知道是否可以在没有框架的情况下将许多依赖项扩展到大型对象图。

此外,鼓励对我的想法/措辞/基本原理进行更正——我基本上是通过 Google/HN/SO 学习到的大部分内容。

4

6 回答 6

5

与 Matlab 无关的答案:

如果(A 需要 B)和(B 需要 C),那么您首先创建 C,然后创建 B 并将 C 传递给 B。然后创建 A 并将(B 有 C)传递给 A。

现在,如果 C 需要注入依赖项,则将其称为 D,您仍然可以在此事件序列之后使用 setter 注入来执行此操作。如果依赖项对于 C 来说是可选的,就会出现这种情况。否则,在程序初始化中可能存在缺陷,即 C 在传递给 B之前没有注入 D。

如果您想在已经拥有(A 拥有(B 拥有 C))之后使用构造函数注入将 D 注入 C,那么您必须使用 setter 注入将新的(C 拥有 D)传递给 B,但是这个序列事件的数量通常不是 DI 的有效场景。

于 2009-02-20T14:05:20.057 回答
3

免责声明:OO 语言不可知的答案

不,您不需要通过整个对象图传递依赖关系。不必实例化具体类型或将它们作为参数传递是 DI 的重点。通常,您将拥有一些其他实体,例如称为 Assembler,它将注入这些依赖项。汇编器可以是临时的、手写的,也可以是一些 DI 框架。

例如:

  • 类 ClsA 具有类型接口 IB 的属性。
  • ClsB 类实现 IB 并具有类型接口 IC 的属性。
  • ClsC 类实现 IC。

您的汇编程序将引导应用程序并:

  1. 创建名为 oC 的 ClsC 类实例
  2. 创建名为 oB 的 ClsB 实例并将其注入 oC
  3. 创建名为 oA 的实例并将其注入 oB

您所有的域对象都只知道接口。Assembler 知道所有的对象,但它的目的只是创建对象图并让所有东西都运动起来。手写汇编程序非常合适;有些人更喜欢编写接线代码而不是使用配置文件。如果您不打算多次使用它,请不要认为编写汇编程序(DI 框架)是值得的。关键是你的类是用 DI 方式编写的。

看看这篇文章: http: //books.google.com/books ?id=vRxAnRb3mb4C&pg=PP1&dq=Danijel+Arsenovski#PPA428,M1

于 2009-02-20T16:33:04.833 回答
2

滚动您自己的 IoC 容器,您可以在其中请求您的依赖项而无需注入它们,或者使用静态网关模式获取单例以使用工厂动态创建类。

我发现这个视频对这些主题非常有用 - http://www.dnrtv.com/default.aspx?showNum=126

于 2009-02-20T14:00:19.723 回答
2

如果你手动进行依赖注入,你最好不要传递依赖。您只需使用其依赖项创建 C,使用 C 创建 B,使用 B 创建 A。A 无需了解有关 C 或其依赖项的任何信息。它只知道 B 的接口,并且通常依赖项不是对象接口的一部分。

于 2009-02-20T14:04:43.973 回答
2

如果我正确理解您的问题,答案可能取决于您如何创建实例化对象的类。在最新版本的 MATLAB 中,可以通过两种方式定义类:“值”类或“句柄”类(此处的 MATLAB 文档)。从文档中引用:

  • 值类: “值类的对象与分配给它们的变量永久关联。复制值对象时,也会复制对象的数据,并且新对象与原始对象的更改无关。实例的行为类似于标准MATLAB 数值和结构类。”

  • 句柄类: “句柄类的对象使用句柄来引用类的对象。句柄是标识类的特定实例的变量。当句柄对象被复制时,句柄被复制,而不是其中存储的数据对象的属性。副本指的是与原始对象相同的数据——如果您更改原始对象的属性值,则复制的对象会反映相同的更改。

下面的示例代码提供了一些示例,说明如何与上面描述的“嵌套”对象进行交互,包括值类嵌套对象和句柄类嵌套对象:

% 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'));

如您所见,使用句柄类可以通过将句柄(本质上是指针)的副本存储在另一个变量中来帮助您避免将函数调用和字段引用链接起来。句柄类还消除了用对这些对象进行操作的方法返回的新副本覆盖对象的旧副本的需要。

希望这对您的要求有所帮助。

于 2009-02-20T16:34:10.727 回答
0

对Matlab一无所知,但我假设(从你的话)有对象。如果是这样,请使用服务定位器而不是依赖注入。服务定位器实现起来非常简单,因此不需要框架。

于 2009-02-20T14:11:36.937 回答