Szukam wzorów lub wskazówek architektonicznych dla nadchodzącej funkcji, którą projektuję. Zasadniczo jest to funkcja eksportu z wieloma celami eksportu i szukam sposobu, aby uczynić ją wystarczająco ogólną, w której podłączanie nowych celów eksportu nie wymaga wielu podstawowych zmian. Podając cele eksportu, po prostu odnoszę się do różnych typów danych wyjściowych, niezależnie od tego, czy są to pliki PDF, prezentacje PowerPoint, dokumenty Word, RSS itp. Mam podstawowy zestaw danych, który jest reprezentowany w JSON i XML. Dane te są wykorzystywane do tworzenia obrazów (przy użyciu dowolnej liczby lub typów eksportu [np. PNG, JPG, GIF itp.), Wykresów, reprezentacji tekstowych, tabel i innych.
Próbuję znaleźć sposób na wyodrębnienie całego renderowania i układu w jakiś silnik renderowania lub układu, który obsługuje dodawanie kolejnych celów eksportowych. Każda pomoc / sugestie / zasoby dotyczące tego, jak podejść do tego, byłyby bardzo mile widziane. Z góry dziękuję.
Dla obrazowego przedstawienia tego, co próbuję osiągnąć.
źródło
Odpowiedzi:
Dla mnie właściwą drogą byłyby interfejsy i fabryka. Jeden, który zwraca odniesienia do interfejsów, za którymi mogą się ukrywać różne klasy. Klasy, które wykonują rzeczywistą pracę z pomrukami, muszą zostać zarejestrowane w fabryce, aby wiedziała, którą klasę utworzyć, biorąc pod uwagę zestaw parametrów.
Uwaga: zamiast interfejsów można również używać abstrakcyjnych klas bazowych, ale wadą jest to, że w przypadku pojedynczych języków dziedziczenia ogranicza cię to do pojedynczej klasy bazowej.
Kod ma składnię Delphi (Pascal), ponieważ jest to język, z którym jestem najbardziej zaznajomiony.
Po zarejestrowaniu wszystkich klas implementujących w fabryce powinieneś móc poprosić o odwołanie do interfejsu dla instancji takiej klasy. Na przykład:
powinien zwrócić odwołanie IReader do instancji TXMLReader; odwołanie IWriter do wystąpienia TPowerPointWriter i odwołanie IRepresentation do wystąpienia THTMLTable.
Teraz wszystko, co musi zrobić silnik renderowania, to powiązanie wszystkiego razem:
Interfejs IReadera powinien zapewniać metody odczytu danych potrzebnych implementatorom IRepresentation do konstruowania reprezentacji danych. Podobnie IReprezentacja powinna zapewnić metody, których implementatorzy IWriter potrzebują do eksportowania reprezentacji danych do żądanego formatu pliku eksportu.
Zakładając, że dane w twoich plikach mają charakter tabelaryczny, IReader i obsługiwane przez niego interfejsy mogą wyglądać następująco:
Iteracja nad stołem byłaby wtedy kwestią
Ponieważ reprezentacje mogą mieć obrazy, wykresy i charakter tekstowy, IRpresentation prawdopodobnie miałby podobne metody do IReadera do przechodzenia przez skonstruowaną tabelę i miałby metody uzyskiwania obrazów i wykresów, na przykład jako strumień bajtów. Do implementatorów IWriter należałoby zakodowanie wartości tabeli i bajtów obrazu / wykresu zgodnie z wymaganiami celu eksportu.
źródło
Chociaż zgadzam się, że potrzeba więcej informacji, aby pomyśleć o architekturze, najprostszym sposobem tworzenia różnego rodzaju obiektów, które zachowują się tak samo (tj. Wszystkie wygenerują dane wyjściowe), jest użycie wzorca fabrycznego. Więcej informacji tutaj
źródło
Możesz skończyć z czymś takim.
Dwie fabryki opierają się na:
1 - do konwersji typu wejściowego (Json / XML) na konkretną implementację sposobu konwertowania tych danych na obraz / wykres
2 - Druga fabryka do decydowania o sposobie renderowania danych wyjściowych do dokumentu Word / Dokument PDF
Polimorfizm używa wspólnego interfejsu dla wszystkich renderowanych danych. Obraz / tabelę można więc przenosić jako prosty interfejs.
1 - Fabryka do konwersji danych JSON / XML do konkretnej implementacji:
Fabryka poniżej pozwala przekonwertować dane XML lub Json Data na właściwy typ betonu.
Konkretne wdrożenia wykonują całą ciężką pracę polegającą na przekształceniu danych w odpowiedni typ. Konwertują również dane do interfejsu IConvertedData, który jest wykorzystywany w przypadku polimorfizmu.
W razie potrzeby możesz dodać te implementacje w miarę rozszerzania kodu.
Interfejs IConvertedData pozwala przekazać pojedynczy typ do następnej fazy: UWAGA: Być może nie zwracasz tutaj pustek. Może to być bajt [] dla obrazów lub dokument OpenXml dla WordDocument. Dostosuj w razie potrzeby.
Wielopostaciowość:
Służy do konwersji danych na odpowiedni typ danych wyjściowych. tzn. renderowanie do pliku PDF dla danych obrazu, może być innym renderingiem danych obrazu dla programu PowerPoint.
2 - Fabryka decyduje o formacie wyjściowym:
Każda konkretna implementacja udostępnia wspólną metodę, która maskuje sposób, w jaki eksport jest zwracany do implementacji IConvertedData
Przykładowy klient do tego wszystkiego to:
źródło
Podobny problem rozwiązaliśmy tutaj: https://ergebnisse.zensus2011.de/?locale=pl Mamy w większości „tabele” i „wykresy” do eksportu w różnych formatach: pdf, excel, web. Naszym pomysłem było określenie każdego obiektu, który ma być renderowany jako własna klasa Java z interfejsami do tworzenia i czytania tych klas. W twoim przypadku będą 2 implementacje dla każdego obiektu do tworzenia (xml, json) i 4 implementacje do renderowania (czytania).
Przykład: Potrzebne będą pewne klasy dla tabel: Tabela klas (obsługuje strukturę tabeli, sprawdzanie poprawności i zawartość) Interfejs CreateTable (udostępnia dane tabeli, komórki, zakresy, treść) Interfejs ReadTable (pobierające wszystkie dane)
Prawdopodobnie nie potrzebujesz interfejsów (lub tylko jednego), ale myślę, że zawsze zapewnia dobre oddzielenie, szczególnie przydatne w testowaniu.
źródło
Myślę, że szukasz wzoru strategii . Masz wiele klas do wyprowadzania danych w pożądanym formacie i po prostu wybierasz odpowiednią w czasie wykonywania. Dodanie nowego formatu powinno być tak proste, jak dodanie innej klasy, która implementuje wymagany interfejs. Często robiłem to w Javie, używając Springa, aby po prostu utrzymywać mapę konwerterów, przypisaną do typu formatu.
Jak wspomnieli inni, zazwyczaj jest to realizowane przez zaimplementowanie przez wszystkie klasy tego samego interfejsu (lub zejście z tej samej klasy bazowej) i wybranie implementacji za pośrednictwem fabryki.
źródło