Navázání na další otázku ( Návrhové rozhodnutí o čtení údajů modelu ze vstupního souboru ).
Chtěl bych se zeptat na další otázku týkající se vzoru stavitele nebo továrny. (Četl jsem, že stavitel je složitější než továrna a prozatím možná nebudu muset používat stavitel). Tady jsou data, která musím číst:
TABLE: "DEGREES OF FREEDOM" X=Yes Y=Yes Z=Yes R1=Yes R2=Yes R3=Yes TABLE: "ANALYSIS OPTIONS" Solver=Advanced SolverProc=Advanced TABLE: "COORDINATE SYSTEMS" Name=GLOBAL Type=Cartesian X=0 Y=0 Z=0 TABLE: "GRID LINES" CoordSys=GLOBAL AxisDir=X GridID=A XRYZCoord=-720 LineColor=Gray8Dark Visible=Yes CoordSys=GLOBAL AxisDir=X GridID=B XRYZCoord=-432 LineColor=Gray8Dark Visible=Yes CoordSys=GLOBAL AxisDir=X GridID=C XRYZCoord=-144 LineColor=Gray8Dark Visible=Yes CoordSys=GLOBAL AxisDir=X GridID=D XRYZCoord=144 LineColor=Gray8Dark Visible=Yes CoordSys=GLOBAL AxisDir=X GridID=E XRYZCoord=432 LineColor=Gray8Dark Visible=Yes CoordSys=GLOBAL AxisDir=X GridID=F XRYZCoord=720 LineColor=Gray8Dark Visible=Yes ...
Existuje mnoho dalších tabulek, jako jsou tyto. Některé tabulky mají nadřazené a podřízené vztahy (Každý souřadný systém má vlastní mřížku). Vytvořil jsem struktury, které představují každou tabulku, například takto:
struct ActiveDOF { bool Ux; bool Uy; bool Uz; bool Rx; bool Ry; bool Rz; }; struct GridLine { enum Direction{X, Y, Z}; enum Type{PRIMARY, SECONDARY}; enum Location{START, END}; std::string coodSystem; Direction direction; std::string gridID; float XRYZ; Type lineType; QColor color; bool visible; Location bubleLoc; bool allVisible; float bubleSize; }; struct CoordinateSystem { std::string name; std::string type; QVector3D center; // center x, center y, cetner z QVector3D about; // aboutx, about y, about z std::vector<GridLine> gridLines; };
tyto datové struktury jsou začleněny do třídy modelu, což vytvoří obrovskou třídu, protože existují 50 zvláštních datových struktur, jako je tato:
class Model { private: ActiveDOF activeDOF; CoordinateSystem coordinateSystem; .... public: Model() {} ... }
každá tabulka musí mít nastavenou metodu a metodu get. Tento design mě znepokojuje, protože pokud se rozhodnu jej změnit, bude to velmi časově náročné. Oceňuji jakýkoli návrh. Myslím, že zde uvedené informace také dají dřívější otázku do lepšího světla.
Teď nevím, kam by měl stavitel nebo tovární metoda jít, vzhledem k situaci. Podíval jsem se na nějaký kód a grafy UML, ale nebyl jsem schopen pochopit, jak implementovat továrnu nebo stavitele abych vytvořil struktury požadované pro můj návrh. Musím mít přístup ke každé tabulce podle jména, protože by se mohly uvnitř modelu změnit, takže se zatím vyhýbám tomu, aby každý z nich byl podtřídou virtuální základní třídy, abych je mohl uložit do kontejneru.
Má také smysl, že místo deklarování instance datové struktury bych na ně měl ponechat ukazatel? pokud jsou všechny datové struktury odvozeny z virtuální základní třída s názvem Record, pak bude model něco takového:
class Model { private: ActiveDOF* activeDOF; CoordinateSystem* coordinateSystem; .... std::Vector<Record*> data; public: Model() {} ... }
Myslím, že je přidělení, dislokace paměti pro ně extra práce, ale to může pomoci se správou dat a zachovat další psaní? mám pravdu v předpokladu, že?
Komentáře
Odpověď
Snažíte se vyřešit problém s přístupem k datům a ten vyžaduje řešení pro přístup k datům.
Nejprve se podívejme na navrhovaná řešení a proč neřeší problémy, které máte.
Tovární vzor
Tovární návrhový vzor (nazývaný také vzor tovární metody) je užitečný, když chcete využít polymorfismus a chcete úplně oddělit konstrukci objektu od implementačních tříd.
V programování založeném na třídách vzor tovární metody je tvůrčí vzor , který používá tovární metody k řešení problému vytváření objektů bez nutnosti specifikovat přesná třída objektu, který bude vytvořen. To se provádí vytvořením objektů voláním tovární metody — zadané v rozhraní a implementováno podřízenými třídami nebo implementováno v základní třídě a volitelně přepsáno odvozenými třídami — spíše než voláním konstruktoru .
(důraz, můj)
A dále to rozvádí problémy, které tento vzor řeší:
Návrhový vzor Factory Method řeší problémy jako:
- Jak lze vytvořit objekt takže dílčí třídy mohou předefinovat, která třída má být vytvořena?
- Jak může třída odložit instanci na podtřídy?
Problémy, které ve své otázce popisujete, se od nich liší. Nejednáte se o podtřídy nebo polymorfismus. Tovární vzor není řešením.
Vzor stavitele
Vzor stavitele (z Wikipedia ):
Builder je návrhový vzor navržený tak, aby poskytoval flexibilní řešení různých problémů s vytvářením objektů v objektově orientovaném programování. Záměrem návrhového vzoru Builderu je oddělit konstrukci složitého objektu od jeho reprezentace.
(důraz, důl)
Zde opět vidíme nesoulad mezi popisovaným problémem a zamýšleným použitím tohoto vzoru.
Návrhový vzor Builderu řeší problémy jako:
- Jak může třída (stejný konstrukční proces) vytvořit různé reprezentace složitý objekt ?
- Jak může třída, která zahrnuje vytvoření složitý objekt zjednodušit?
(důraz, důl)
Klíčem je zde konstrukce objektu (objekt = 1 objekt) je složitá. Může to být kvůli velkému počtu argumentů konstruktoru nebo kvůli složitosti sestavení jeho závislostí.
Každá struktura nebo třída je jednotlivě docela jednoduchá, takže ani vzor stavitele není vhodný.
Vzory přístupu k datům (řešení)
Problémy, které se skutečně snažíte vyřešit, spočívají v tom, jak provést přístup k datům, a možná hledáte Objekt pro přístup k datům .
V počítačovém softwaru je objekt pro přístup k datům (DAO) je objekt, který poskytuje abstraktní rozhraní k určitému typu databáze nebo jinému mechanismu perzistence. Mapováním volání aplikace do vrstvy perzistence , DAO poskytuje některé konkrétní datové operace bez odhalení podrobností o databázi.
Ve vašem případě nahraďte „databázi“ výrazem „textový soubor“. Související návrhový vzor je Návrhový vzor úložiště , který rozděluje přístup k datům na 3 hlavní řešení:
- Repository — veřejné rozhraní pro „přístup k datům“
- brána — ví, jak mluvit s databází Oracle nebo číst / zapisovat do textový soubor. To by zahrnovalo serializaci objektů a struktur na SQL nebo datový formát očekávaný v textovém souboru.
- Factory — mapuje data vrácená bránou na objekty a struktury použitý zbytkem vaší aplikace
Vlastnictví paměti
Protože nemáte výhodu / omezení automatické správy paměti, vlastnictví paměti přidělené těchto objektů a struktur je určitě problém. Zde se musíte rozhodnout:
- Je objekt přístupu k datům odpovědný za vyčištění této paměti?
- Má objekt přístupu k datům očekáváte, že volající (klientský kód) převezme odpovědnost za uvolnění této paměti?
Pokud je objekt pro přístup k datům vytvořen při spuštění aplikace a trvá do ukončení aplikace, přístup k datům objekt by mohl převzít vlastnictví této paměti.
Pokud je objekt pro přístup k datům vytvořen na vyžádání a poté zlikvidován, je třeba, aby se kód klienta ujistil, že je tato paměť čistá ned up.
Definujte to v komentářích nebo dokumentaci k objektu pro přístup k datům a vynuťte to při kontrole kódu.
Komentáře
- Líbí se mi tento přístup. Vypadá mnohem flexibilněji. Cokoli jiného, o co se zeptám, odhalí moji nevědomost v této věci. Mám implementovat DAO sám? Jak tomu rozumím, měl bych napsat Gateway and Factory? Je brána stejná jako vzor mostu GOF?
- Řekl bych, že brána ve vzoru úložiště je další variaci vzoru mostu. Ve skutečnosti to vypadá, že základem vzoru úložiště je více organizovaný a koordinovaný vzor mostu zaměřený konkrétně na přístup k datům. A ano, ‚ tyto komponenty pravděpodobně budete muset napsat sami.
- Po zveřejněných odkazech jsem se dostal k en.wikipedia.org/wiki/ODB_(C%2B%2B) , Jak tento ODB zapadá do obrázku? Mohu napsat program, který převede můj textový vstup na sqllite a poté použít ODB pro vytrvalost? je to zvuk? Musím říct, že jsem právě narazil na ODB a podíval se na dva příklady, takže to není informovaný komentář.
- Pomoc s psaním kódu je pro tento web mimo téma, nicméně jsem si ‚ jistý, že můžete text převést na sqlite a použít existující knihovnu.
Odpověď
Tvůrce by byl „postaven“ uvnitř továrního invarientu (metoda), čímž by přečetl textový soubor, napíšete 1 továrnu s metodou čtení uvedeného souboru. Nyní, pokud potřebujete postupně sestavovat model z dat, která jste načetli (myslíte si, že jsou vnořená data), vzor stavitele uvnitř metody továrny by vám dobře posloužil. K načtení dat však pravděpodobně postačí jeden model.
Komentáře
- Některý pseudokód může být velmi užitečný. Nikdy předtím jsem nepoužíval tovární nebo stavitelské vzory.
Odpověď
Vzhledem k velikosti a složitosti vaší struktury nejvhodnější se zdá být stavitel, zvláště pokud je váš model (nebo jej lze vytvořit) neměnný. Budete muset akceptovat těsné propojení mezi tvůrcem a modelem, ale stojí za to, zvláště pokud budete muset vytvářet modely na více místech. Tvůrce také umožňuje zapouzdřit ověření.
Pokud je však váš model proměnlivý a je vytvořen pouze na jednom místě, může být vhodnější a účelnější továrna a do hry vstupuje společnost YAGNI.
V reakci na vaši další otázku , nikdy byste neměli ukládat raw ukazatele v C ++. Faktem je, že std::unique_ptr
nemá žádné stinné stránky a bagatelizuje ničení objektů. Když tento vektor vyjde z rozsahu, nezbaví jej paměti odkazy psané, ale s unique_ptr by to bylo.
Vytvořil bych vektor pro velké množství opakujících se prvků, zejména pokud se množství pravděpodobně změní, ale pro středně velké komponenty, které nejsou nikdy sdíleny, byste je mohli zahrnout přímo do struktury.
Model
(nebo různé derivace společné základní třídyModelBase
neboIModel
) a chcete centralizovat rozhodnutí o tom, která konkrétní derivace bude vytvořena. ‚ Nevidím tento problém ve vaší otázce, jaký je tedy váš ‚ nápad používat továrnu?