Model de fabrică sau model de constructor? care este potrivit pentru citirea datelor modelului de element finit dintr-un fișier text?

O continuare a unei alte întrebări ( Luarea unei decizii de proiectare cu privire la citirea datelor modelului dintr-un fișier de intrare ).

Aș dori să pun o altă întrebare cu privire la modelul constructorului sau al fabricii. (Am citit că constructorul este mai complex decât fabrica și s-ar putea să nu fiu nevoit să folosesc constructorul deocamdată). Așadar, iată datele pe care trebuie să le citesc:

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

Există mult mai multe tabele ca acestea. Unele tabele au relații părinte, copil (Fiecare sistem de coordonate are o linie de grilă proprie). Am realizat structuri care reprezintă fiecare tabel, astfel:

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

aceste structuri de date sunt încorporate în clasa modelului, ceea ce va face o clasă imensă, deoarece există 50 de structuri de date ciudate ca aceasta:

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

fiecare tabel trebuie să aibă metoda setată și metoda get. Acest design mă îngrijorează deoarece, dacă decid să îl schimb, va consuma mult timp. Apreciez orice sugestie. Cred că și informațiile de aici vor pune întrebarea anterioară într-o lumină mai bună.

Acum, nu știu unde ar trebui să meargă metoda constructorului sau fabricii, având în vedere situația. Am analizat câteva diagrame de cod și UML, dar nu am putut înțelege cum să implementez fabrica sau constructorul pentru a face structurile necesare pentru proiectarea mea. Trebuie să am acces la fiecare tabel în funcție de nume, deoarece acestea ar putea fi supuse modificărilor în interiorul modelului, așa că, deocamdată, evit să fac din fiecare dintre acestea o subclasă a unei clase de bază virtuale, astfel încât să le pot stoca într-un container.

De asemenea, are sens că, în loc să declar o instanță a structului de date, ar trebui să păstrez un pointer la ele? dacă toate structurile de date sunt derivate dintr-un clasa de bază virtuală numită Record, atunci modelul va fi ceva de genul acesta:

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

Cred că este o muncă suplimentară pentru a aloca, dislocă memoria pentru ei, vă poate ajuta în gestionarea datelor și să păstrez mai mult tastarea? Am dreptate presupunând că?

Comentarii

  • I ‘ mn nu sunt sigur că răspunsul este una dintre alegerile dvs. Modelul fabricii este de obicei utilizat în combinație cu polimorfismul. Modelul constructor este utilizat atunci când construcția obiectelor este complexă. Nu ‘ t folosiți polimorfism și fiecare structură este destul de simplă. aceasta pare doar o simplă ” cum fac acces la date ” întrebare.
  • ” Fabrica ” și ” Builder ” rezolvă diferite probleme . ” Fabrica ” ar fi potrivită dacă aveți derivări diferite din clasa Model (sau diferite derivări ale unei clase de bază comune ModelBase sau IModel) și doriți să centralizați decizia cu privire la care derivare concretă este instanțiată. Nu ‘ nu văd această problemă în întrebarea dvs., deci care este ‘ ideea dvs. în spatele utilizării unei fabrici aici?

Răspuns

Încercați să rezolvați o problemă de acces la date și necesită o soluție de acces la date.

Mai întâi, să examinăm soluțiile propuse și de ce nu rezolvă problemele pe care le aveți.

Modelul Factory

Modelul Factory Design (numit și Modelul Factory Method) este util atunci când doriți să utilizați polimorfismul și doriți să separați complet construcția obiectelor de clasele de implementare.

Wikipedia :

În programarea bazată pe clase, modelul metodei din fabrică este un model de creație care folosește metodele din fabrică pentru a rezolva problema creării obiectelor fără a fi nevoie să specificați clasa exactă a obiectului care va fi creat. Acest lucru se face prin crearea obiectelor apelând o metodă din fabrică — fie specificată în o interfață și implementată de clase de copii, sau implementată într-o clasă de bază și opțional suprascrisă de clase derivate — mai degrabă decât apelând un constructor .

(subliniere, a mea)

Și mai jos se detaliază problemele rezolvate de acest model:

Modelul de proiectare a Metodei fabricii rezolvă probleme precum:

  • Cum poate fi creat un obiect astfel încât subclasele să poată redefini ce clasă să instanțieze?
  • Cum poate o clasă să amâne instanțierea la subclase?

Problemele pe care le descrieți în întrebarea dvs. sunt diferite de acestea. Nu aveți de-a face cu subclasele sau polimorfismul. Modelul din fabrică nu este o soluție.

Modelul Builder

Modelul Builder (din Wikipedia ):

Builder este un model de proiectare conceput pentru a oferi o soluție flexibilă diferitelor probleme de creare a obiectelor în programarea orientată pe obiecte. Intenția modelului de proiectare Builder este de a separa construcția unui obiect complex de reprezentarea acestuia.

(accent, al meu)

Aici, din nou, vedem o nepotrivire între problema pe care o descrieți și utilizarea intenționată a acestui model.

Modelul de proiectare Builder rezolvă probleme precum:

  • Cum poate o clasă (același proces de construcție) să creeze reprezentări diferite ale unui obiect complex ?
  • Cum poate o clasă care include crearea unui obiect complex simplificat?

(accent, al meu)

Cheia aici este construcția unui obiect (un obiect = 1 obiect) este complexă. Acest lucru s-ar putea datora unui număr mare de argumente de constructor sau datorită complexității asamblării dependențelor sale.

În mod individual, fiecare structură sau clasă este destul de simplă, deci nici modelul constructor nu se potrivește bine.

Modele de acces la date (soluția)

Problemele pe care efectiv le încercați să le rezolvați sunt cum să efectuați accesul la date și este posibil să căutați un Obiect de acces la date .

În software-ul computerului, un obiect de acces la date (DAO) este un obiect care oferă o interfață abstractă către un anumit tip de bază de date sau alt mecanism de persistență. Prin maparea apelurilor de aplicații la stratul de persistență , DAO oferă câteva operații specifice de date fără a expune detalii despre baza de date.

În cazul dvs., înlocuiți „baza de date” cu „fișier text”. Un model de proiectare asociat este Modelul de proiectare a depozitului , care împarte accesul la date în 3 soluții principale:

  • Depozit interfața publică pentru „acces la date”
  • Gateway — știe cum să vorbească cu o bază de date Oracle sau să citească / scrie pe un fișier text. Aceasta ar include serializarea obiectelor și structurilor către SQL sau formatul de date așteptat în fișierul text.
  • Factory — mapează datele returnate de Gateway către obiectele și structurile utilizat de restul aplicației dvs.

Proprietatea memoriei

Deoarece nu aveți avantajul / limitarea gestionării automate a memoriei, proprietatea memoriei alocate aceste obiecte și structuri sunt cu siguranță o preocupare. Aici trebuie să luați o decizie:

  • Este obiectul de acces la date responsabil pentru curățarea acestei memorii?
  • Obiectul de acces la date vă așteptați ca apelantul (codul clientului) să își asume responsabilitatea pentru eliberarea acestei memorii?

Dacă obiectul de acces la date este creat când pornește aplicația și trăiește până când aplicația este oprită, accesul la date obiectul ar putea deține proprietatea asupra acestei memorii.

Dacă obiectul de acces la date este creat la cerere și apoi eliminat, codul clientului trebuie să se asigure că această memorie este clea finalizat.

Definiți acest lucru în comentariile sau documentația pentru obiectul de acces la date și aplicați acest lucru în revizuirea codului.

Comentarii

  • Îmi place această abordare. Arată mult mai flexibil. Orice alt lucru pe care îl voi cere îmi va dezvălui ignoranța în acest sens. Ar trebui să implementez DAO singur? În modul în care îl înțeleg, ar trebui să scriu Gateway și Factory? Gateway-ul este același cu modelul GOF bridge?
  • Aș spune că gateway-ul din modelul depozitului este o altă variantă a modelului bridge. De fapt, se pare că fundamentul modelului depozitului este un model bridge mai organizat și coordonat axat în mod special pe accesul la date. Și da, ‘ probabil va trebui să scrieți singur aceste componente.
  • urmând linkurile pe care le-ați postat, am ajuns la en.wikipedia.org/wiki/ODB_(C%2B%2B) , Cum se încadrează acest ODB în imagine? Pot scrie un program pentru a-mi converti textul în sqllite și apoi să folosesc ODB pentru persistență? este sunet? Trebuie să spun că tocmai am dat peste ODB și am privit două exemple, deci nu este un comentariu informat.
  • Asistența pentru scrierea codului nu este subiect pentru acest site, totuși sunt ‘ sigur că puteți converti textul în sqlite și puteți utiliza o bibliotecă existentă.

Răspuns

Un constructor ar fi „construit” în interiorul unei fabrici invarient (metodă), pentru a citi un fișier text, ai scrie 1 fabrică cu o metodă pentru a citi fișierul menționat. Acum, dacă trebuie să vă construiți în mod incremental modelul din datele pe care le-ați citit (gândiți-vă la date imbricate), modelul constructor din metoda din fabrică vă va servi bine. Cu toate acestea, un singur model va fi suficient pentru a vă încărca datele în.

Comentarii

  • Unele pseudo-coduri vă pot ajuta să auziți. Nu am mai folosit niciodată modele de fabrică sau constructor.

Răspuns

Având în vedere dimensiunea și complexitatea structurii dvs., un constructor pare cel mai potrivit, mai ales dacă modelul dvs. este (sau poate fi făcut) imuabil. Va trebui să acceptați o cuplare strânsă între constructor și model, dar merită probleme, mai ales dacă va trebui să construiți modele în mai multe locuri. Un constructor vă permite, de asemenea, să încapsulați validarea.

Cu toate acestea, dacă modelul dvs. este modificabil și este creat doar într-un singur loc, atunci o fabrică ar putea fi mai adecvată și mai oportună și YAGNI va intra în joc.


Ca răspuns la cealaltă întrebare , nu ar trebui să stocați niciodată indicii raw în C ++. Faptul este că std::unique_ptr nu are dezavantaje și banalizează distrugerea obiectelor. Când acel vector iese din scop, nu va elibera memoria referințe scrise, dar cu un unic_ptr, ar fi.

Aș crea un vector pentru cantități mari de elemente repetate, mai ales dacă este posibil ca cantitatea să se schimbe, dar pentru componentele de dimensiuni medii care nu sunt partajate niciodată, le-ați putea include și direct în struct.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *