【发布时间】:2011-06-24 09:32:14
【问题描述】:
我有一个关于松散耦合和接口的概念/理论问题。
所以使用接口的一种方法可能是封装某个构造函数所需的参数:
class Foo
{
public Foo(IFooInterface foo)
{
// do stuff that depends on the members of IFooInterface
}
}
所以只要传入的对象实现了契约,一切都会工作。据我了解,这里的主要好处是它支持多态性,但我不确定这是否真的与松散耦合有关。
为了论证,假设 IFooInterface 如下:
interface IFooInterface
{
string FooString { get; set; }
int FooInt { get; set; }
void DoFoo(string _str);
}
从松耦合的角度来看,不要在上面的构造函数中使用 IFooInterface 会更好,而是像这样设置 Foo:
class Foo
{
public Foo(string _fooString, int _fooInt, Action<string> _doFoo)
{
// do the same operations
}
}
因为说我想把 Foo 的功能放到另一个项目中。这意味着其他项目也必须引用 IFooInterface,添加另一个依赖项。但是这样我可以把 Foo 放到另一个项目中,它准确地表达了它需要什么才能工作。显然我可以只使用重载的构造函数,但是为了论证的缘故,我不想和/或不能修改 Foo 的构造函数。
最显着的缺点(至少对我而言)是,如果您有一个带有一堆原始参数的方法,它会变得丑陋且难以阅读。所以我有了创建一种包装函数的想法,它允许您仍然传递接口而不是所有原始类型:
public static Func<T, R> Wrap<T, R>(Func<T, object[]> conversion)
{
return new Func<T, R>(t =>
{
object[] parameters = conversion(t);
Type[] args = new Type[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
{
args[i] = parameters[i].GetType();
}
ConstructorInfo info = typeof(R).GetConstructor(args);
return (R)info.Invoke(parameters);
});
}
这里的想法是,我可以取回一个函数,该函数采用符合 Foo 要求的某个接口的实例,但 Foo 对那个接口一无所知。可以这样使用:
public Foo MakeFoo(IFooInterface foo)
{
return Wrap<IFooInterface, Foo>(f =>
new object[] { f.FooString, f.FooInt, f.DoFoo })(foo);
}
我听说过关于接口应该如何启用松散耦合的讨论,但对此感到疑惑。
想知道一些有经验的程序员是怎么想的。
【问题讨论】:
-
我认为你让事情变得不必要地复杂了。
-
松散耦合的目标是不 任何一方都不应该引用另一方。接口是一个(非常)有用的语言特性。没有理由避开它们。
-
我对松散耦合的印象是,我应该能够接受一个类(或更抽象地说是一组属性/行为)并理解它的目的,而不管某些特定的上下文,或者,就像我说的 drop将它放到另一个项目中,并且看不到一堆消息,例如“找不到类型或命名空间 x”。我的问题不是我们是否应该避开接口,我的问题是它们是否真的旨在促进松散耦合,或者它们是否更意味着多态/继承?
-
所有代码都存在于特定的上下文中。松散耦合只是意味着一个类不需要知道它所依赖的类的私密细节。接口可以通过明确说明类的哪些公共成员用于公共消费以及哪些是特定于实现的来帮助解决这个问题。
标签: c# interface dependencies primitive-types loose-coupling