I used this template many times in different places, usually next to the plugin.
In some examples, I used it for messaging systems, such as creating subscribers for various types of unrelated messages. I also used it for general integration workflows, each of which needs a context-sensitive form object.
Basically, a template consists of defining an empty token interface for a message or context. Next, define a high-level workflow interface that works with the message / context interface. You can then use the factory to get a specific instance of the workflow, and if necessary, the workflow can also be responsible for parsing its message / context from the general data format.
Then you create an abstract common base workflow, the responsibility of which is only to map the calls to the interface methods that go around the useless token interface, to the calls to abstract methods that accept a specific version of the message / context.
Hope this makes sense. I will give an example code below. I would like to know if this template has a name because I noticed that I used it about 4-5 times. Also, I am just explaining how to explain the pattern, so if anything about my explanation does not make sense, let me know.
The main thing is that you can have several classes with different method signatures that can still be called through a common interface:
Final result
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){...}
}
public void Main(){
var data = GetDataFromIntegrationSource(someContext);
IWorkflow impl = Factory.GetConcrete(someContext);
IMessage msg = impl.Parse(data);
impl.Process(msg);
}
FULL EXAMPLE
High Level Interfaces
public interface IGenericeMarkerInterface
{
}
public interface IGenericWorkflow
{
void Process(IGenericeMarkerInterface messageOrContext);
IGenericeMarkerInterface Parse(IDictionary<string, string> commonDataFormat);
}
An abstract base for mapping concrete methods
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);
}
Match Attributes
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)
{
}
public override SomeRandomlyShapedMessageOrContext DoParse(IDictionary<string, string> commonDataFormat)
{
}
}
Factory
public static class WorkflowFactory
{
public static IGenericWorkflow Get(WorkflowType workflow)
{
}
}
public static class Program
{
public static void Main(string[] args)
{
var someSortOfWorkflowIdentifier = (WorkflowType)args[0];
var data = GetSomeDictionaryOfData();
var workflow = WorkflowFactory.Get(someSortOfWorkflowIdentifier);
workflow.Process(workflow.Parse(data));
}
}