これは私がすることです:
Linkを抽象クラスとして保持し、Factoryを使用してインスタンス化し、クロージャー/匿名メソッドをFactoryのbuildメソッドのパラメーターとして渡します。このようにして、Linkを抽象クラスとして使用して元の設計を維持し、ファクトリ全体に実装を強制し、ファクトリ内にLinkの具体的な痕跡を隠すことができます。
次にいくつかのサンプルコードを示します。
class Program
{
static void Main(string[] args)
{
Link link = LinkFactory.GetLink("id", () =>
// This would be your onClick method.
{
// SetResponsePage(...);
Console.WriteLine("Clicked");
Console.ReadLine();
});
link.FireOnClick();
}
public static class LinkFactory
{
private class DerivedLink : Link
{
internal DerivedLink(String id, Action action)
{
this.ID = id;
this.OnClick = action;
}
}
public static Link GetLink(String id, Action onClick)
{
return new DerivedLink(id, onClick);
}
}
public abstract class Link
{
public void FireOnClick()
{
OnClick();
}
public String ID
{
get;
set;
}
public Action OnClick
{
get;
set;
}
}
}
編集:実際には、これはあなたが望むものに少し近いかもしれません:
Link link = new Link.Builder
{
OnClick = () =>
{
// SetResponsePage(...);
},
OnFoo = () =>
{
// Foo!
}
}.Build("id");
利点は、initブロックを使用することで、Linkクラス内のアクションのオプションの実装を必要な数だけ宣言できることです。
これが関連するLinkクラスです(封印されたBuilder内部クラスを使用)。
public class Link
{
public sealed class Builder
{
public Action OnClick;
public Action OnFoo;
public Link Build(String ID)
{
Link link = new Link(ID);
link.OnClick = this.OnClick;
link.OnFoo = this.OnFoo;
return link;
}
}
public Action OnClick;
public Action OnFoo;
public String ID
{
get;
set;
}
private Link(String ID)
{
this.ID = ID;
}
}
これはあなたが探しているものに近いですが、オプションの名前付き引数、C#4.0機能を使用してさらに一歩進めることができると思います。オプションの名前付き引数を使用したLinkの宣言例を見てみましょう。
Link link = Link.Builder.Build("id",
OnClick: () =>
{
// SetResponsePage(...);
Console.WriteLine("Click!");
},
OnFoo: () =>
{
Console.WriteLine("Foo!");
Console.ReadLine();
}
);
なんでこんなにかっこいいの?新しいLinkクラスを見てみましょう。
public class Link
{
public static class Builder
{
private static Action DefaultAction = () => Console.WriteLine("Action not set.");
public static Link Build(String ID, Action OnClick = null, Action OnFoo = null, Action OnBar = null)
{
return new Link(ID, OnClick == null ? DefaultAction : OnClick, OnFoo == null ? DefaultAction : OnFoo, OnBar == null ? DefaultAction : OnBar);
}
}
public Action OnClick;
public Action OnFoo;
public Action OnBar;
public String ID
{
get;
set;
}
private Link(String ID, Action Click, Action Foo, Action Bar)
{
this.ID = ID;
this.OnClick = Click;
this.OnFoo = Foo;
this.OnBar = Bar;
}
}
静的クラスBuilderの内部には、1つの必須パラメーター(ID)と3つのオプションパラメーターOnClick、OnFoo、およびOnBarを受け取るファクトリメソッドBuildがあります。それらが割り当てられていない場合、ファクトリメソッドはそれらにデフォルトの実装を提供します。
したがって、Linkのコンストラクターのパラメーター引数では、必要なメソッドを実装するだけで済みます。そうしないと、デフォルトのアクションが使用されますが、これは何もない可能性があります。
ただし、最後の例では、Linkクラスが抽象的ではないという欠点があります。ただし、コンストラクターがプライベートであるため(Linkをインスタンス化するためにBuilderクラスを使用するように強制する)、Linkクラスのスコープ外でインスタンス化することはできません。
オプションのパラメーターをLinkのコンストラクターに直接移動して、ファクトリの必要性を完全に回避することもできます。