Fabrikkmønster eller byggmønster? hvilken er egnet for å lese Finite Element Model-data fra en tekstfil?

En oppfølging av et annet spørsmål ( Ta en designbeslutning om å lese modelldata fra en inngangsfil ).

Jeg ønsker å stille et annet spørsmål angående byggmester eller fabrikkmønster. (Jeg leste at byggmester er mer kompleks enn fabrikken, og jeg trenger kanskje ikke å bruke byggmester for nå). Så her er dataene jeg må lese:

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 ... 

Det er mange flere tabeller som disse. Noen tabeller har foreldre-, underforhold (hvert koordinatsystem har sin egen rutenett). Jeg har laget strukturer som representerer hver tabell, slik:

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; }; 

disse datastrukturene er innlemmet i modellklassen, noe som vil gi en enorm klasse siden det er 50 rare datastrukturer som dette:

class Model { private: ActiveDOF activeDOF; CoordinateSystem coordinateSystem; .... public: Model() {} ... } 

hver tabell må ha sin angitte metode og få metoden. Denne designen bekymrer meg, for hvis jeg bestemmer meg for å endre den, vil den være veldig tidkrevende. Jeg setter pris på ethvert forslag. Jeg tror informasjonen her også vil sette det tidligere spørsmålet i et bedre lys.

Nå vet jeg ikke hvor byggherren eller fabrikkmetoden skal gå, gitt situasjonen. Jeg så på noen kode og UML-diagrammer, men jeg var ikke i stand til å forstå hvordan jeg skulle implementere fabrikken, eller byggherre å lage strukturer som kreves for designet mitt. Jeg må ha tilgang til hver tabell ved navn, fordi de kan bli endret inne i modellen, så foreløpig unngår jeg å gjøre hver av dem til en underklasse av en virtuell baseklasse, slik at jeg kan lagre dem i en container.

Er det også fornuftig at jeg i stedet for å erklære en forekomst av datastrukturen, bør holde en peker til dem? hvis alle datastrukturer er avledet fra en virtuell baseklasse kalt Record, så vil modellen være noe sånt som dette:

class Model { private: ActiveDOF* activeDOF; CoordinateSystem* coordinateSystem; .... std::Vector<Record*> data; public: Model() {} ... } 

Jeg tror det er ekstra arbeid å tildele, fjerne minne til dem, men det kan hjelpe med å administrere dataene og fortsette å skrive ekstra? Har jeg rett i å anta det?

Kommentarer

  • I ‘ mn ikke sikker på at svaret er et av dine valg. Fabrikkmønsteret brukes vanligvis i kombinasjon med polymorfisme. Bygningsmønsteret brukes når objektkonstruksjonen er kompleks. Du bruker ikke ‘ polymorfisme, og hver struktur er ganske enkel. dette virker bare som et rett opp » hvordan gjør jeg datatilgang » spørsmål.
  • » Fabrikk » og » Builder » løser forskjellige problemer . » Fabrikk » vil være egnet hvis du har forskjellige avledninger av Model -klassen (eller forskjellige avledninger av en felles basisklasse ModelBase eller IModel), og du vil sentralisere avgjørelsen om hvilken konkret avledning som blir instantiert. Jeg ser ikke ‘ dette problemet i spørsmålet ditt, så hva ‘ er ideen din bak å bruke en fabrikk her?

Svar

Du prøver å løse et datatilgangsproblem, og det krever en datatilgangsløsning.

La oss først undersøke de foreslåtte løsningene dine, og hvorfor de ikke løser problemene du har.

Fabrikkmønsteret

Fabrikkdesignmønsteret (også kalt fabrikkmetodemønsteret) er nyttig når du vil bruke polymorfisme og du vil skille objektkonstruksjon helt fra implementeringsklassene.

Wikipedia :

I klassebasert programmering, fabrikkmetodemønsteret er et skapelsesmønster som bruker fabrikkmetoder for å håndtere problemet med å lage objekter uten å måtte spesifisere nøyaktig klasse av objektet som skal opprettes. Dette gjøres ved at oppretter objekter ved å kalle en fabrikkmetode — enten spesifisert i et grensesnitt og implementert av underordnede klasser, eller implementert i en basisklasse og eventuelt overstyrt av avledede klasser — i stedet for ved å ringe en konstruktør .

(utheving, min)

Og lenger nede utdyper den problemene dette mønsteret løser:

Fabrikkmetodens designmønster løser problemer som:

  • Hvordan kan et objekt opprettes slik at underklasser kan omdefinere hvilken klasse som skal instantieres?
  • Hvordan kan en klasse utsette instantiering til underklasser?

Problemene du beskriver i spørsmålet ditt, er forskjellige fra disse. Du har ikke å gjøre med underklasser eller polymorfisme. Fabrikkmønsteret er ikke en løsning.

Byggmønsteret

Byggmønsteret (fra Wikipedia ):

The Builder er et designmønster designet for å gi en fleksibel løsning på ulike objektopprettingsproblemer i objektorientert programmering. Hensikten med Builder-designmønsteret er å skille konstruksjonen av et komplekst objekt fra dets representasjon.

(utheving, min)

Her ser vi igjen en uoverensstemmelse mellom problemet du beskriver og den tiltenkte bruken av dette mønsteret.

Builder-designmønsteret løser problemer som:

  • Hvordan kan en klasse (samme byggeprosess) lage forskjellige representasjoner av en komplekst objekt ?
  • Hvordan kan en klasse som inkluderer å opprette en komplekst objekt bli forenklet?

(utheving, min)

Nøkkelen her er konstruksjonen til et objekt (et objekt = 1 objekt) er komplekst. Dette kan være på grunn av et stort antall konstruktørargumenter, eller på grunn av kompleksiteten ved å montere dens avhengigheter.

Hver enkelt struktur eller klasse er individuelt ganske enkel, så byggemønsteret passer heller ikke.

Data Access Patterns (The Solution)

Problemene du faktisk prøver å løse er hvordan du utfører datatilgang, og du leter kanskje etter en Data Access Object .

I dataprogramvare er et datatilgangsobjekt (DAO) er et objekt som gir et abstrakt grensesnitt til en eller annen type database eller annen utholdenhetsmekanisme. Ved å kartlegge applikasjonssamtaler til utholdenhetslaget , DAO gir noen spesifikke datahandlinger uten å avsløre detaljer om databasen.

I ditt tilfelle erstatter du «database» med «tekstfil». Et relatert designmønster er Repository Design Pattern , som deler datatilgang i tre hovedløsninger:

  • Repository — det offentlige grensesnittet for «data access stuff»
  • Gateway — vet å snakke med en Oracle-database eller lese / skrive til en tekstfil. Dette vil omfatte serieisering av objekter og strukturer til SQL eller det dataformatet som forventes i tekstfilen.
  • Fabrikk — kartlegger data som returneres av gatewayen til objektene og strukturene brukt av resten av applikasjonen din

Eierskap til minne

Siden du ikke har fordelen / begrensningen av automatisk styring av minne, eier du minnet tildelt disse objektene og strukturene er definitivt en bekymring. Her må du ta en avgjørelse:

  • Er datatilgangsobjektet ansvarlig for å rydde opp i dette minnet?
  • Har datatilgangsobjektet forvente at den som ringer (klientkode) tar ansvar for å frigjøre dette minnet?

Hvis datatilgangsobjektet opprettes når applikasjonen starter, og lever til applikasjonen stenges, blir datatilgangen objektet kan ta eierskapet til dette minnet.

Hvis datatilgangsobjektet opprettes på forespørsel og deretter kastes, må klientkoden sørge for at dette minnet er rent ned opp.

Definer dette i kommentarene eller dokumentasjonen for datatilgangsobjektet, og håndhev dette i kodegjennomgang.

Kommentarer

  • Jeg liker denne tilnærmingen. Ser mye mer fleksibelt ut. Alt annet jeg ber om vil avsløre min uvitenhet om saken. Skal jeg implementere DAO selv? Slik jeg forstår det, bør jeg skrive Gateway and Factory? Er Gateway det samme som bro-GOF-mønster?
  • Jeg vil si at gatewayen i depotmønsteret er en annen variant av bromønsteret. Faktisk ser det ut til at grunnlaget for depotmønsteret er et mer organisert og koordinert bromønster fokusert spesielt på datatilgang. Og ja, du ‘ vil sannsynligvis trenge å skrive disse komponentene selv.
  • etter lenkene du la ut, fikk jeg til en.wikipedia.org/wiki/ODB_(C%2B%2B) , Hvordan denne ODBen passer inn i bildet? Jeg kan skrive et program for å konvertere tekstinntastingen min til sqllite og deretter bruke ODB for utholdenhet? er dette lyden? Jeg må si at jeg bare snublet over ODB og så på to eksempler, så dette er ikke en informert kommentar.
  • Hjelp til å skrive kode er utenfor emnet for dette nettstedet, men jeg ‘ er sikker på at du kan konvertere teksten til sqlite og bruke et eksisterende bibliotek.

Svar

En byggmester ville bli «bygget» inne i en fabrikkinparent (metode), og dermed lese en tekstfil, du ville skrive en fabrikk med en metode for å lese filen. Nå, hvis du trenger å bygge modellen din trinnvis fra dataene du leser (tenk nestede data), vil byggemønsteret i fabrikkmetoden tjene deg godt. Imidlertid vil en enkelt modell nok være tilstrekkelig for å laste inn dataene dine.

Kommentarer

  • Noe pseudokode kan være nyttig å høre. Jeg har aldri brukt fabrikk- eller byggemønstre før.

Svar

Gitt størrelsen og kompleksiteten i strukturen din, en byggherre virker mest hensiktsmessig, spesielt hvis modellen din er (eller kan gjøres) uforanderlig. Du må godta en tett kobling mellom byggherren og modellen, men det er verdt bryet, spesielt hvis du trenger å bygge modeller flere steder. En byggmester lar deg også kapsle validering.

Men hvis modellen din er mutbar og bare er opprettet på ett sted, kan en fabrikk være mer hensiktsmessig og hensiktsmessig, og YAGNI kommer til spill.


Som svar på det andre spørsmålet ditt , bør du aldri lagre rå pekere i C ++. Faktum er at std::unique_ptr ikke har noen ulemper, og det bagatelliserer ødeleggelse av objekter. Når denne vektoren går utenfor omfanget, vil den ikke frigjøre minnet referanser som skrevet, men med en unik_ptr, ville det.

Jeg vil lage en vektor for store mengder repeterende elementer, spesielt hvis mengden sannsynligvis vil endres, men for mellomstore komponenter som aldri deles, kan du like godt inkludere dem direkte i strukturen.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *