緩い結合とインターフェースについて、概念的/理論的な質問があります。
したがって、インターフェースを使用する1つの方法は、特定のコンストラクターに必要なパラメーターをカプセル化することです。
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);
}
インターフェイスがどのようにルーズカップリングを可能にするかについての議論を聞いたことがありますが、これについて疑問に思っていました。
一部の経験豊富なプログラマーがどう思うか疑問に思います。