Есть имя для этого шаблона
Я использовал этот шаблон много раз в разных местах, обычно рядом с шаблоном плагина.
Некоторые примеры способов, которые я использовал, предназначены для систем обмена сообщениями, таких как создание подписчиков на различные типы несвязанных сообщений. Я также использовал его для общих интеграционных рабочих процессов, каждый из которых нуждается в объекте контекста различной формы.
В основном шаблон состоит из определения пустого интерфейса маркера для сообщения или контекста. Затем определение интерфейса рабочего процесса высокого уровня, который работает с интерфейсом сообщения / контекста. Затем вы можете использовать фабрику для получения конкретного экземпляра рабочего процесса, и, если необходимо, рабочий процесс также может быть ответственным за синтаксический анализ своего сообщения / контекста из общего формата данных.
Затем вы создаете абстрактный базовый базовый рабочий процесс, который отвечает только за отображение вызовов на методы интерфейса, которые передают интерфейс бесполезного маркера, на вызовы абстрактных методов, которые принимают конкретную версию сообщения / контекста.
Надеюсь, это имеет смысл. Я приведу пример кода ниже. Я хотел бы знать, есть ли у этого паттерна имя, потому что я заметил, что использовал его 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));
}
}