我已经多次在各种场合使用了这种模式,通常与插件模式一起使用。
例如,我将其用于消息系统,创建订阅不相关消息的各种类型。我也将其用于通用集成工作流,每个工作流需要一个形状不同的上下文对象。
基本上,该模式包括为消息或上下文定义一个空标记接口。然后定义一个高级工作流接口,该接口与消息/上下文接口一起工作。然后,您可以使用工厂获取工作流的具体实例,如果需要,工作流还可以负责从常见数据格式解析其消息/上下文。
接下来,创建一个抽象的通用基础工作流,其职责仅是将对接口方法的调用(传递无用的标记接口)映射到调用抽象方法,以获取消息/上下文的具体版本。
希望这样能够让你理解。下面提供一个代码示例。我想知道这个模式是否有名称,因为我已经注意到自己已经使用了4-5次。另外,我正在完善如何解释这个模式,如果我解释得不清楚,请告诉我。
最重要的一点是,您可以拥有具有不同方法签名的多个类,但仍然可以通过公共接口调用它们:
抽象基类用于映射具体方法
例如,我将其用于消息系统,创建订阅不相关消息的各种类型。我也将其用于通用集成工作流,每个工作流需要一个形状不同的上下文对象。
基本上,该模式包括为消息或上下文定义一个空标记接口。然后定义一个高级工作流接口,该接口与消息/上下文接口一起工作。然后,您可以使用工厂获取工作流的具体实例,如果需要,工作流还可以负责从常见数据格式解析其消息/上下文。
接下来,创建一个抽象的通用基础工作流,其职责仅是将对接口方法的调用(传递无用的标记接口)映射到调用抽象方法,以获取消息/上下文的具体版本。
希望这样能够让你理解。下面提供一个代码示例。我想知道这个模式是否有名称,因为我已经注意到自己已经使用了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));
}
}