कई प्रकार के निर्यात के लिए एक मजबूत वास्तुकला डिजाइन करना?


10

मैं एक आगामी सुविधा के लिए पैटर्न या वास्तु मार्गदर्शन की तलाश कर रहा हूं जो मैं डिजाइन कर रहा हूं। मूल रूप से, यह कई निर्यात लक्ष्यों के साथ एक निर्यात सुविधा है, और मैं इसे सामान्य बनाने के लिए एक रास्ता खोजने के लिए देख रहा हूं, जहां नए निर्यात लक्ष्यों में प्लगिंग के लिए बहुत अधिक बदलाव की आवश्यकता नहीं है। निर्यात लक्ष्य द्वारा, मैं बस विभिन्न प्रकार के आउटपुट का उल्लेख कर रहा हूं, चाहे वह पीडीएफ हो, पावरपॉइंट प्रेजेंटेशन, वर्ड डॉक्यूमेंट, आरएसएस, आदि। मेरे पास डेटा का एक बेस सेट है, जो JSON और XML में दर्शाया गया है। इस डेटा का उपयोग छवियों के निर्माण के लिए किया जाता है (किसी भी संख्या या निर्यात प्रकार [जैसे, पीएनजी, जेपीजी, जीआईएफ, आदि), रेखांकन, पाठीय अभ्यावेदन, टेबल, और बहुत कुछ।

मैं किसी तरह के रेंडरिंग या लेआउट इंजन में सभी रेंडरिंग और लेआउट को अमूर्त करने का एक तरीका खोजने की कोशिश कर रहा हूं जो आगे के निर्यात लक्ष्यों को जोड़ने का काम करता है। किसी भी मदद / सुझाव / संसाधनों के रूप में कैसे इस दृष्टिकोण के लिए बहुत सराहना की जाएगी। अग्रिम में धन्यवाद।

जो मैं हासिल करने की कोशिश कर रहा हूं, उसके एक सचित्र प्रतिनिधित्व के लिए।

यहां छवि विवरण दर्ज करें


क्या आप बता सकते हैं कि आपने अब तक क्या प्रयास किया है? लेआउट इंजन की आवश्यकताएँ (जिम्मेदारियाँ) क्या हैं? उदाहरण के लिए, क्या पेजिंग और पृष्ठ आकार चयन को संभालने की उम्मीद है?
6'13

क्या XML / JSON डेटा का उपयोग एक ही आउटपुट रन पर कई आउटपुट प्रकार बनाने के लिए किया जा सकता है, अर्थात आपका XML डेटा PDF दस्तावेज़ में चित्र और तालिकाएँ और ग्राफ़ बनाता है? या XML / JSON डेटा का उपयोग केवल PDF दस्तावेज़ के लिए एक तालिका या ग्राफ़ बनाने के लिए किया जा सकता है?
गिब्सन

यह सब xkcd.com/927 के बारे में है - आप पहिया को फिर से मजबूत करने की कोशिश क्यों कर रहे हैं? DocBook, Markdown / pandoc इत्यादि पहले से ही मौजूद हैं ...
हिरण हंटर

जवाबों:


2

मेरे लिए, जाने का रास्ता इंटरफेस और फैक्टरी होगा। एक जो विभिन्न स्थानों को छुपा सकता है, जिसके पीछे इंटरफेस का संदर्भ देता है। जो कक्षाएं वास्तविक ग्रन्ट काम करती हैं, उन्हें सभी को कारखाने के साथ पंजीकृत करने की आवश्यकता होती है, ताकि यह पता चल सके कि किस वर्ग ने मापदंडों का एक सेट तुरंत दिया है।

नोट: इंटरफेस के बजाय आप एब्सट्रैक्ट बेस क्लासेस का भी इस्तेमाल कर सकते हैं, लेकिन इसका दोष यह है कि सिंगल इनहेरिटेंस भाषाओं के लिए यह आपको सिंगल बेस क्लास तक सीमित करता है।

TRepresentationType = (rtImage, rtTable, rtGraph, ...);

Factory.RegisterReader(TJSONReader, 'json');
Factory.RegisterReader(TXMLReader, 'xml');

Factory.RegisterWriter(TPDFWriter, 'pdf');
Factory.RegisterWriter(TPowerPointWriter, 'ppt');
Factory.RegisterWriter(TWordWriter, 'doc');
Factory.RegisterWriter(TWordWriter, 'docx');

Factory.RegisterRepresentation(TPNGImage, rtImage, 'png');
Factory.RegisterRepresentation(TGIFImage, rtImage, 'gif');
Factory.RegisterRepresentation(TJPGImage, rtImage, 'jpg');
Factory.RegisterRepresentation(TCsvTable, rtTable, 'csv');
Factory.RegisterRepresentation(THTMLTable, rtTable, 'html');
Factory.RegisterRepresentation(TBarChart, rtTGraph, 'bar');
Factory.RegisterRepresentation(TPieChart, rtTGraph, 'pie');

कोड डेल्फी (पास्कल) सिंटैक्स में है क्योंकि यह वह भाषा है जिसके साथ मैं सबसे अधिक परिचित हूं।

सभी कार्यान्वयन कक्षाएं कारखाने के साथ पंजीकृत होने के बाद, आपको ऐसे वर्ग के उदाहरण के लिए इंटरफ़ेस संदर्भ का अनुरोध करने में सक्षम होना चाहिए। उदाहरण के लिए:

Factory.GetReader('SomeFileName.xml');
Factory.GetWriter('SomeExportFileName.ppt');
Factory.GetRepresentation(rtTable, 'html');

TXMLReader के उदाहरण के लिए एक IReader संदर्भ लौटाना चाहिए; TPWPointWriter की एक आवृत्ति के लिए एक IWriter संदर्भ और THTMLPable की आवृत्ति के लिए एक IRepresentation संदर्भ।

अब सभी रेंडरिंग इंजन को करने की जरूरत है, सब कुछ एक साथ टाई है:

procedure Render(
  aDataFile: string; 
  aExportFile: string;
  aRepresentationType: TRepresentationType;
  aFormat: string;
  );
var
  Reader: IReader;
  Writer: IWriter;
  Representation: IRepresentation;
begin
  Reader := Factory.GetReaderFor(aDataFile);
  Writer := Factory.GetWriterFor(aExportFile);
  Representation := Factory.GetRepresentationFor(aRepresentationType, aFormat);

  Representation.ConstructFrom(Reader);
  Writer.SaveToFile(Representation);
end;

IReader इंटरफ़ेस को डेटा के प्रतिनिधित्व का निर्माण करने के लिए IRepresentation कार्यान्वयनकर्ताओं द्वारा आवश्यक डेटा को पढ़ने के तरीके प्रदान करने चाहिए। इसी तरह IRepresentation को ऐसे तरीके प्रदान करने चाहिए जो IWriter कार्यान्वयनकर्ताओं को अनुरोधित निर्यात फ़ाइल प्रारूप में डेटा प्रतिनिधित्व को निर्यात करने की आवश्यकता हो।

मान लें कि आपकी फ़ाइलों में डेटा प्रकृति में सारणीबद्ध है, IReader और इसके सहायक इंटरफेस इस तरह दिख सकते हैं:

IReader = interface(IInterface)
  function MoveNext: Boolean;
  function GetCurrent: IRow;
end;

IRow = interface(IInterface)
  function MoveNext: Boolean;
  function GetCurrent: ICol;
end;

ICol = interface(IInterface)
  function GetName: string;
  function GetValue: Variant;
end;

एक मेज पर घूमना फिर बात होगी

while Reader.MoveNext do
begin
  Row := Reader.GetCurrent;
  while Row.MoveNext do
  begin
    Col := Row.GetCurrent;
    // Do something with the column's name or value
  end;
end;

जैसा कि अभ्यावेदन प्रकृति में चित्र, रेखांकन और शाब्दिक हो सकते हैं, IRepresentation में एक निर्मित तालिका को पार करने के लिए IReader के समान तरीके होंगे और इसमें चित्र और रेखांकन प्राप्त करने के तरीके होंगे, उदाहरण के लिए बाइट्स की एक धारा के रूप में। यह IWriter कार्यान्वयनकर्ताओं के लिए होगा जो निर्यात लक्ष्य द्वारा आवश्यक तालिका मान और छवि / ग्राफ़ बाइट्स को एन्कोड करें।


1

जबकि मैं मानता हूं कि वास्तुकला के बारे में सोचने के लिए अधिक जानकारी की आवश्यकता है, विभिन्न प्रकार की वस्तुओं को बनाने का सबसे सरल तरीका है जो समान व्यवहार करते हैं (यानी उनमें से सभी एक आउटपुट उत्पन्न करेंगे) कारखाने पैटर्न का उपयोग कर रहे हैं। अधिक जानकारी यहाँ

फैक्ट्री मेथड पैटर्न, ऑब्जेक्ट की सटीक क्लास को निर्दिष्ट किए बिना ऑब्जेक्ट्स (उत्पाद) बनाने की समस्या से निपटने के लिए फैक्ट्रियों की अवधारणा को लागू करने के लिए एक ऑब्जेक्ट-ओरिएंटेड क्रिएशनल डिज़ाइन पैटर्न है। इस पैटर्न का सार "किसी ऑब्जेक्ट को बनाने के लिए एक इंटरफ़ेस को परिभाषित करना है, लेकिन इंटरफ़ेस को लागू करने वाले वर्गों को तुरंत तय करने दें। फ़ैक्टरी विधि एक वर्ग को उप-वर्गों में तत्काल स्थगित करने देती है।" विकिपीडिया से


1
मुझे लगता है कि यह उससे थोड़ा अधिक शामिल है। उदाहरण के लिए, आरेख में लाइनों के साथ डेटा संचार करने के लिए कौन से प्रोटोकॉल का उपयोग किया जाएगा? क्या रेंडरिंग / लेआउट इंजन में एक सामान्य डेटा प्रतिनिधित्व हो सकता है, या यह इंजन पूरी तरह से कस्टम तरीकों के लिए एक कारखाना है, जो आरेख में प्रत्येक पंक्ति के लिए एक है?
रॉबर्ट हार्वे

यकीन नहीं होता अगर मुझे आपकी बात यहाँ मिल गई। क्योंकि यदि आरेख में लाइनों को संप्रेषित करने के लिए एक प्रोटोकॉल का उपयोग करने की आवश्यकता है, तो मैं सोच रहा हूं कि मैं निर्यात उत्पन्न करने के लिए सेवाओं के एक सेट पर भरोसा कर रहा हूं (इस मामले में आप कुछ सोआ / एकीकरण पैटर्न देखना चाहेंगे)। यहां तक ​​कि अगर यह सच है, तो समाधान लचीला और कारखाने के उपयोग के लिए पर्याप्त मजबूत है। हो सकता है कि आप जो काम करना चाहते हैं वह एक कनवर्टर इंटरफ़ेस बनाना है जिसमें दो विधियाँ हैं: एक जो XML डेटा प्राप्त करता है और दूसरा JSON डेटा। दोनों के लिए वापसी वस्तु परिवर्तित वस्तु होगी। इस तरह से आप जो चाहें इकट्ठा कर सकते हैं।
ऑर्पोस्यूसर

हेडर में वास्तव में दो प्रश्न हैं: सामग्री के बारे में (gif, pdf, html) और परिवहन के बारे में (स्थानीय फ़ाइल, http-response-item)। @Orposuser (+1) उत्तर का विस्तार करने के लिए: मैं एक फैक्ट्री का उपयोग करके एक स्ट्रीम बनाऊंगा जिसे आसानी से बिना लाइसेंस के और आसानी से http-response के लिए रेंडर किया जा सकता है।
k3b

0

आप कुछ इस तरह से समाप्त कर सकते हैं।

दो कारखानों के आसपास आधारित हैं:

1 - इनपुट प्रकार (Json / XML) को इस डेटा को छवि / ग्राफ़ में परिवर्तित करने के ठोस कार्यान्वयन के लिए

2 - एक वर्ड डॉक्यूमेंट / पीडीएफ डॉक्यूमेंट में आउटपुट रेंडर करने का निर्णय लेने के लिए एक दूसरा कारखाना

बहुरूपता सभी प्रदान किए गए डेटा के लिए एक सामान्य इंटरफ़ेस का उपयोग करता है। तो एक छवि / तालिका को आसान इंटरफ़ेस के रूप में चारों ओर ले जाया जा सकता है।

1 - JSON / XML डेटा को एक ठोस कार्यान्वयन में बदलने के लिए कारखाना:

public enum DataTypeToConvertTo
{
    Image,
    Table,
    Graph,
    OtherData
}

public interface IDataConverter
{
    IConvertedData ConvertJsonDataToOutput(Json jsonData);
    IConvertedData ConvertXmlDataToOutput(XDocument xmlData);
}

public abstract class DataConverter : IDataConverter
{
    public DataConverter()
    {

    }

    public abstract IConvertedData ConvertDataToOutput(string data);
}

नीचे दी गई फैक्ट्री आपको xml Data या Json Data को सही ठोस प्रकार में बदलने की अनुमति देती है।

public class DataConverterFactory
{
    public static IDataConverter GetDataConverter(DataTypeToConvertTo dataType)
    {
        switch(dataType)
        {
            case DataTypeToConvertTo.Image:
                return new ImageDataConverter();
            case DataTypeToConvertTo.Table:
                return new TableDataConverter();
            case DataTypeToConvertTo.OtherData:
                return new OtherDataConverter();
            default:
                throw new Exception("Unknown DataTypeToConvertTo");
        }
    }
}

ठोस कार्यान्वयन डेटा को संबंधित प्रकार में परिवर्तित करने के सभी भारी कार्य करते हैं। वे डेटा को IConvertedData इंटरफ़ेस में भी परिवर्तित करते हैं, जिसका उपयोग बहुरूपता के लिए किया जाता है।

public sealed class ImageDataConverter : DataConverter
{
    public ImageDataConverter()
        : base()
    {

    }

    public override IConvertedData ConvertJsonDataToOutput(Json jsonData)
    {
        var convertedData = new ImageConvertedData();
        //Logic to convert to necessary datatype

        return convertedData;
    }

    public override IConvertedData ConvertXmlDataToOutput(XDocument xmlData)
    {
        var convertedData = new ImageConvertedData();
        //Logic to convert to necessary datatype

        return convertedData;
    }
}

public sealed class TableDataConverter : DataConverter
{
    public TableDataConverter()
        : base()
    {

    }

    public override IConvertedData ConvertJsonDataToOutput(Json jsonData)
    {
        var convertedData = new TableConvertedData();
        //Logic to convert to necessary datatype

        return convertedData;
    }

    public override IConvertedData ConvertXmlDataToOutput(XDocument xmlData)
    {
        var convertedData = new ImageConvertedData();
        //Logic to convert to necessary datatype

        return convertedData;
    }
}

public sealed class OtherDataConverter : DataConverter
{
    public OtherDataConverter()
        : base()
    {

    }

    public override IConvertedData ConvertJsonDataToOutput(Json jsonData)
    {
        var convertedData = new OtherConvertedData();
        //Logic to convert to necessary datatype

        return convertedData;
    }

    public override IConvertedData ConvertXmlDataToOutput(XDocument xmlData)
    {
        var convertedData = new OtherConvertedData();
        //Logic to convert to necessary datatype

        return convertedData;
    }
}

आप इन कार्यान्वयनों को आवश्यक रूप से जोड़ सकते हैं, जैसा कि आपका कोड फैलता है।

IConvertedData इंटरफ़ेस आपको अगले चरण में एक एकल प्रकार पास करने की अनुमति देता है: नोट: आप यहां voids नहीं लौटा सकते हैं। यह छवियों के लिए एक बाइट [] या WordDocument के लिए एक OpenXml दस्तावेज़ हो सकता है। आवश्यकतानुसार समायोजित करें।

public interface IConvertedData
{
    void RenderToPdf();
    void RenderToDocument();
    void RenderToOhter();
    void RenderToPowerPoint();
}

बहुरूपता:

इसका उपयोग डेटा को संबंधित आउटपुट प्रकार में परिवर्तित करने के लिए किया जाता है। यानी इमेज डेटा के लिए पीडीएफ रेंडर करना, पावरपॉइंट के लिए अलग-अलग इमेज डेटा रेंडर करना हो सकता है।

public sealed class ImageConvertedData : IConvertedData
{
    public void RenderToPdf()
    {
        //Logic to render Images
    }

    public void RenderToDocument()
    {
        //Logic to render Images
    }
}
public sealed class TableConvertedData : IConvertedData
{
    public void RenderToPdf()
    {
        //Logic to render Document
    }

    public void RenderToDocument()
    {
        //Logic to render Document
    }
}

public sealed class OtherConvertedData : IConvertedData
{
    public void RenderToPdf()
    {
        //Logic to render PDF
    }

    public void RenderToDocument()
    {
        //Logic to render PDF
    }
}

2 - फैक्टरी उत्पादन प्रारूप तय करने के लिए:

public enum ExportOutputType
{
    PDF,
    PowerPoint,
    Word,
    Other
}

public interface IOutputExporter
{
    void ExportData(IConvertedData data);
}


public class OutputExporterFactory
{
    public static IOutputExporter GetExportOutputType(ExportOutputType exportOutputType)
    {
        switch(exportOutputType)
        {
            case ExportOutputType.PDF:
                return new OutputExporterPdf();
            case ExportOutputType.PowerPoint:
                return new OutputExporterPowerPoint();
            case ExportOutputType.Other:
                return new OutputExporterOther();
            default:
                throw new Exception ("Unknown ExportOutputType");
        }
    }
}

प्रत्येक ठोस कार्यान्वयन एक सामान्य विधि को उजागर करता है जो यह बताता है कि कैसे निर्यात को IConvertedData कार्यान्वयन में वापस फेंक दिया जा रहा है

public abstract class OutputExporter : IOutputExporter
{
    //Other base methods...
    public virtual void ExportData(IConvertedData data)
    {

    }
}

public sealed class OutputExporterPdf : OutputExporter
{
    public OutputExporterPdf()
        : base()
    {

    }

    public override void ExportData(IConvertedData data)
    {
        //Functionality to Export to Pdf
        data.RenderToPdf();
    }
}

public sealed class OutputExporterPowerPoint : OutputExporter
{
    public OutputExporterPowerPoint()
        : base()
    {

    }

    public override void ExportData(IConvertedData data)
    {
        //Functionality to Export to PowerPoint
        data.RenderToPowerPoint();
    }
}

public sealed class OutputExporterOther : OutputExporter
{
    public OutputExporterOther()
        : base()
    {

    }

    public override void ExportData(IConvertedData data)
    {
        //Functionality to Export to PowerPoint
        data.RenderToOhter();
    }
}

इस सब के लिए एक नमूना ग्राहक होगा:

public class Client
{
    public Client()
    {

    }
    public void StartExportProcess(XDocument data)
    {
        IDataConverter converter = DataConverterFactory.GetDataConverter(DataTypeToConvertTo.Graph);

        IConvertedData convertedData = converter.ConvertXmlDataToOutput(data);


        IOutputExporter exportOutputer = OutputExporterFactory.GetExportOutputType(ExportOutputType.PDF);
        exportOutputer.ExportData(convertedData);
    }
}

0

हमने यहां एक समान समस्या हल की: https://ergebnisse.zanim2011.de/?locale=en हमारे पास अलग-अलग स्वरूपों में निर्यात करने के लिए ज्यादातर "टेबल" और "ग्राफ" हैं: पीडीएफ, एक्सेल, वेब। हमारा विचार उन कक्षाओं को बनाने और पढ़ने के लिए इंटरफेस के साथ प्रत्येक जावा वर्ग के रूप में प्रदान की जाने वाली प्रत्येक वस्तु को निर्दिष्ट करना था। आपके मामले में (xml, json) बनाने के लिए प्रत्येक वस्तु के लिए 2 कार्यान्वयन और प्रतिपादन (पढ़ने) के लिए 4 कार्यान्वयन होंगे।

उदाहरण: आपको टेबल्स के लिए कुछ वर्गों की आवश्यकता होगी: क्लास टेबल (हैंडल टेबल संरचना, सत्यापन और सामग्री) इंटरफ़ेस क्रिएटेबल (टेबल डेटा, सेल, स्पैन, सामग्री प्रदान करता है) इंटरफ़ेस रीडेबल (सभी डेटा के लिए गेटर्स)

संभवतः आपको इंटरफेस (या केवल एक) की आवश्यकता नहीं है, लेकिन मुझे लगता है कि यह हमेशा परीक्षण में विशेष रूप से उपयोगी एक अच्छा डिकम्पलिंग प्रदान करता है।


0

मुझे लगता है कि आप जो देख रहे हैं वह स्ट्रैटेजी पैटर्न है। वांछित प्रारूप में डेटा को आउटपुट करने के लिए आपके पास विभिन्न प्रकार की कक्षाएं हैं, और आप बस रनटाइम में उपयुक्त को चुनते हैं। एक नया प्रारूप जोड़ना एक अन्य वर्ग को जोड़ने के रूप में सरल होना चाहिए जो आवश्यक इंटरफ़ेस को लागू करता है। मैंने अक्सर ऐसा किया है जावा में स्प्रिंग का उपयोग करके बस कन्वर्टर्स का एक नक्शा बनाए रखने के लिए, प्रारूप प्रकार द्वारा कुंजीबद्ध।

जैसा कि दूसरों ने उल्लेख किया है, यह आमतौर पर सभी वर्गों को एक ही इंटरफ़ेस (या एक ही आधार वर्ग से उतरता है) को लागू करने और एक कारखाने के माध्यम से कार्यान्वयन का चयन करके पूरा किया जाता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.