私はこのパターンをさまざまな場所で何度も使用してきましたが、通常はプラグイン パターンと一緒に使用しました。
私がこれを使用したいくつかの例は、さまざまなタイプの無関係なメッセージへのサブスクライバーを作成するなど、メッセージング システム用です。また、それぞれが異なる形状のコンテキスト オブジェクトを必要とする一般的な統合ワークフローにも使用しました。
基本的に、パターンは、メッセージまたはコンテキストの空白のマーカー インターフェイスを定義することで構成されます。次に、メッセージ/コンテキスト インターフェイスと連携する高レベルのワークフロー インターフェイスを定義します。次に、ファクトリを使用してワークフローの具体的なインスタンスを取得できます。必要に応じて、ワークフローは、共通のデータ形式からメッセージ/コンテキストを解析することもできます。
次に、不要なマーカー インターフェイスを通過するインターフェイス メソッドへの呼び出しを、メッセージ/コンテキストの具体的なバージョンを取得する抽象メソッドへの呼び出しにマップすることだけを担当する抽象汎用基本ワークフローを作成します。
うまくいけば、それは理にかなっています。以下にコード例を示します。このパターンに名前があるかどうか知りたいです.4〜5回ほど使用していることに気づいたからです. また、私はパターンを説明する方法を肉付けしているだけなので、私の説明について何か意味がない場合は、それもお知らせください.
重要な点は、共通のインターフェイスを介して呼び出すことができる、異なるメソッド シグネチャを持つ複数のクラスを持つことができるということです。
最終結果
public class ConcreteA : Base<MessageA>
{
public void Process(MessageA message){...}
public MessageA Parse(IDictionary data){...}
}
public class ConcreteB : Base<MessageB>
{
public void Process(MessageB message){...}
public MessageB Parse(IDictionary data){...}
}
//And both can by called by...
public void Main(){
var data = GetDataFromIntegrationSource(someContext);
IWorkflow impl = Factory.GetConcrete(someContext);
//So in your classes you're able to work with strongly typed parameters,
//But in the consuming code you still can use a common interface
//Consuming code never even knows what the strong type is.
IMessage msg = impl.Parse(data);
impl.Process(msg);
}
完全な例
高レベルのインターフェース
public interface IGenericeMarkerInterface
{
}
public interface IGenericWorkflow
{
void Process(IGenericeMarkerInterface messageOrContext);
IGenericeMarkerInterface Parse(IDictionary<string, string> commonDataFormat);
}
具体的なメソッドにマッピングするための抽象ベース
public abstract class GenericWorkflowBase<T> : IGenericWorkflow where T : IGenericeMarkerInterface
{
public void Process(IGenericeMarkerInterface messageOrContext)
{
Process((T)messageOrContext);
}
public IGenericeMarkerInterface Parse(IDictionary<string, string> commonDataFormat)
{
return DoParse(commonDataFormat);
}
public abstract void Process(T messageOrContext);
public abstract T DoParse(IDictionary<string, string> commonDataFormat);
}
マッピング属性
public class MappingAttributeUsedByFactoryAttribute : Attribute
{
public WorkflowType SomePropertyForMapping { get; set; }
}
具体的な実装
public class SomeRandomlyShapedMessageOrContext : IGenericeMarkerInterface
{
public int ID { get; set; }
public string Data { get; set; }
}
[MappingAttributeUsedByFactory(WorkflowType.IntegrationPartnerB)]
public class ConcreteWorkflow : GenericWorkflowBase<SomeRandomlyShapedMessageOrContext>
{
public override void Process(SomeRandomlyShapedMessageOrContext messageOrContext)
{
//TODO: process the strongly typed message
}
public override SomeRandomlyShapedMessageOrContext DoParse(IDictionary<string, string> commonDataFormat)
{
//TODO: parse the common data into the strongly typed message
}
}
工場
public static class WorkflowFactory
{
public static IGenericWorkflow Get(WorkflowType workflow)
{
//TODO: find the concrete workflow by inspecting attributes
}
}
使用例
public static class Program
{
public static void Main(string[] args)
{
//this could be driven by a UI or some contextual data
var someSortOfWorkflowIdentifier = (WorkflowType)args[0];
var data = GetSomeDictionaryOfData();
var workflow = WorkflowFactory.Get(someSortOfWorkflowIdentifier);
workflow.Process(workflow.Parse(data));
}
}