ฉันเคยใช้รูปแบบนี้หลายครั้งในหลายๆ ที่ โดยปกติจะใช้ร่วมกับรูปแบบปลั๊กอิน
ตัวอย่างบางวิธีที่ฉันใช้กับระบบการรับส่งข้อความ เช่น การสร้างผู้สมัครรับข้อความประเภทต่างๆ ที่ไม่เกี่ยวข้อง ฉันยังใช้มันสำหรับเวิร์กโฟลว์การรวมทั่วไปที่แต่ละรายการต้องการออบเจ็กต์บริบทที่มีรูปแบบแตกต่างกัน
โดยพื้นฐานแล้วรูปแบบประกอบด้วยการกำหนดอินเทอร์เฟซเครื่องหมายว่างสำหรับข้อความหรือบริบท จากนั้นกำหนดอินเทอร์เฟซเวิร์กโฟลว์ระดับสูงที่ทำงานกับอินเทอร์เฟซข้อความ/บริบท จากนั้นคุณสามารถใช้โรงงานเพื่อรับตัวอย่างเวิร์กโฟลว์ที่เป็นรูปธรรม และหากจำเป็น เวิร์กโฟลว์ยังสามารถรับผิดชอบในการแยกวิเคราะห์ข้อความ / บริบทจากรูปแบบข้อมูลทั่วไป
ถัดไป คุณสร้างเวิร์กโฟลว์พื้นฐานทั่วไปเชิงนามธรรมซึ่งมีหน้าที่เพียงแมปการเรียกไปยังวิธีอินเทอร์เฟซ ซึ่งส่งผ่านอินเทอร์เฟซตัวทำเครื่องหมายที่ไม่มีประโยชน์ ไปเป็นการเรียกไปยังวิธีนามธรรมที่ใช้ข้อความ/บริบทเวอร์ชันที่เป็นรูปธรรม
หวังว่ามันจะสมเหตุสมผล ฉันจะให้ตัวอย่างรหัสด้านล่าง อยากทราบว่ารูปแบบนี้มีชื่อหรือเปล่า เพราะสังเกตว่าใช้ไปประมาณ 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));
}
}