我有一个关于松散耦合和接口的概念/理论问题。

因此,使用接口的一种方法可能是封装某些构造函数所需的参数:

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>的设置者提供FooStringFooIntIFooInterface的实现可能具有与那些设置程序有关的规则,并且可能需要访问未在接口上公开的其他实现详细信息。

同样,您也应该接受Func<string>Func<int>:随着时间的推移,IFooInterface的实现可能具有关于FooStringFooInt的规则。例如,DoFoo可能会重新计算这些值。您不能假设它们只是传递给永不改变的字段。

进一步讲,如果获取,设置或DoFoo需要访问公共状态,则在创建它们时,函数和操作将需要关闭同一组变量。届时,您将进行一些心理体操,以了解可变寿命和代表之间的关系。

状态和行为的这种配对正是类所表达的,而实现细节的隐藏正是接口提供的。将这些概念分解为它们的组成元素当然是可以实现的,但是这也破坏了通过将成员与类型分组而获得的连贯性。

换句话说,您可以给我面条,酱汁,蔬菜和汉堡包,但这不是意大利面和肉丸:-)

10-01 11:22