我有一个关于松散耦合和接口的概念/理论问题。
因此,使用接口的一种方法可能是封装某些构造函数所需的参数:
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);
}
我听说过有关接口应该如何实现松散耦合的讨论,但对此感到奇怪。
想知道一些经验丰富的程序员的想法。
最佳答案
我的第一个想法是,您没有分别为Action<string>
和Action<int>
的设置者提供FooString
和FooInt
。 IFooInterface
的实现可能具有与那些设置程序有关的规则,并且可能需要访问未在接口上公开的其他实现详细信息。
同样,您也应该接受Func<string>
和Func<int>
:随着时间的推移,IFooInterface
的实现可能具有关于FooString
和FooInt
的规则。例如,DoFoo
可能会重新计算这些值。您不能假设它们只是传递给永不改变的字段。
进一步讲,如果获取,设置或DoFoo
需要访问公共状态,则在创建它们时,函数和操作将需要关闭同一组变量。届时,您将进行一些心理体操,以了解可变寿命和代表之间的关系。
状态和行为的这种配对正是类所表达的,而实现细节的隐藏正是接口提供的。将这些概念分解为它们的组成元素当然是可以实现的,但是这也破坏了通过将成员与类型分组而获得的连贯性。
换句话说,您可以给我面条,酱汁,蔬菜和汉堡包,但这不是意大利面和肉丸:-)