Një program i mirëfilltë që plotëson të gjitha kërkesat e mësipërme do kërkonte të paktën 2-3 javë punë. Shpresoj të jetë me disa faza detyra se vështirë do e kesh të përfundosh gjithçka brenda një jave.
Më poshtë kam hedhur një skelet klasash për programin në C++, por po të shpjegoj edhe logjikën që ndoqa për të dizajnin.
Dizajni
Fillojmë nga elementi më i thjeshtë, PikeGjeografike dhe vazhdojmë me deklarimin e enteve Aeroport dhe Fluturim. Aeroporti përbëhet nga një pikë gjeografike me një emër. Fluturimi përbëhet nga aeroporti i nisjes dhe ai i arritjes.
Më pas vazhdojmë me klasat AeroportParser dhe FluturimParser të cilat lexojnë të dhënat e formatuara dhe kthejnë një listë përkatësisht me Aeroporte ose Fluturime. Në metodat e këtyre klasave do lexosh rreshtat një nga një, do t'i copëtosh në njësi më të vogla të cilat do i përdorësh më pas për të krijuar një Aeroport ose Fluturim të ri.
Entet e të dhënave Aeroport dhe Fluturim duhet t'i ruajmë diku, qoftë në ndonje strukturë të dhënash në memorje, ose një skedar, databazë, etj. Për të bërë programin sa më elastik/fleksibël për të ardhmen, përdorim modelin Data Access Object (DAO) dhe krijojmë AeroportetDAO dhe FluturimetDAO. Këto klasa abstraktojnë ruajtjen dhe hapjen e Aeroporteve dhe Fluturimeve duke na lejuar që t'i zëvendësojmë me vonë sipas dëshirës pa ndryshuar kodin që i thërret ato.
Deri tani kemi krijuar disa ente me informacion, por na duhet një ent tjetër që do menaxhojë entet me informacion për plotësimin e kërkesave të biznesit. Këto detyra ua ngarkojmë enteve të biznesit, AeroportetManager dhe FluturimetManager. Pra, menaxheri bën lidhjen midis anës së biznesit (klientit, përdoruesit) dhe asaj të informacionit; Klienti bën porosinë/kërkesën dhe Menaxherit e plotëson duke pëpunuar informacionin që zotëron (në këtë rast Aeroportet dhe Fluturimet).
Duke vazhduar të analizojmë modelin e biznesit, mund të shikojmë një farë hierarkie midis Menaxherit të Fluturimeve dhe Menaxherit të Aeroporteve. Për këtë arsye e kemi bërë Menaxherin e Aeroporteve vartës të Menaxherit të Fluturimeve në klasën FluturimetManager. Pra, nëse Menaxheri i Fluturimeve ka nevojë për të kryer një detyrë për aeroportet, ia delegon këtë detyrë Menaxherit të Aeroporteve.
Le të marrim një shembull për të kuptuar rrjedhjen e ekzekutimit.
Rrjedhja e ekzekutimit: Përdoruesi ngarkon Aeroportet nga skedari aeroportet.txt
- main() ia jep komandën ngarkoAeroportet skedari KomandëEkzekutuesit
- KomandëEkzekutuesi thërret FluturimetManager.ngarkoAeroportet(string & skedari)
- FluturimetManger thërret AeroportManager.ngarkoAeroportet(string & skedari)
- AeroportManager hap skedarin dhe thërret AerportParser.parseAeroportet(istream & teDhenat)
- AeroportParser thërret istream.get_line(), krijon një PikeGjeografike, dhe pastaj një Aeroport
- AeroportManager merr Aeroportet e kthyer nga AeroportParser dhe thërret AeroportetDAO.shtoAeroportin() për të gjithë aeroportet.
- AeroportetDAO thërret _aeroportet.put(emri, aeroporti)
Ndërtimi i objekteve
Deri tani s'kemi shpjeguar se si do krijohen dhe do lidhen entet e përmendur më lart. Ka dy mënyra për të bërë këtë gjë:
I. Mënyra e parë është që në main() të krijojmë vetëm FluturimetManager; pastaj FluturimetManager krijon FluturimetDAO dhe AeroportManager; AeroportManager krijon AeroportDAO. Pra, klasat krijojnë vartësit e tyre.
II. Mënyra tjetër është që një klasë e vetme (ose në main()) të krijojmë të gjitha klasat dhe t'i lidhim me njëra tjetrën duke i kaluar vartësit si argumente tek ndërtuesit (constructors).
Që të dyja mënyrat kanë të mirat dhe të ligat për të cilat nuk po zgjatem më tej sepse do dilja jashtë teme. Mendoj se mënyra e dytë është më lehtë për fillestarët e C++.
Vër re se parser-at nuk kanë nevojë të krijohen sepse thërriten në mënyrë statike.
Kodi në C++
Kodi PHP:
// Klasa për të prezantuar një pikë gjeografike
class PikeGjeografike {
private:
double _gjeresia;
double _gjatesia;
public:
PikeGjeografike(double gjeresia, double gjatesia);
double merrGjeresia() const;
double merrGjatesia() const;
};
Kodi PHP:
// Klasa për të prezantuar një aeroport
class Aeroport {
private:
string _emri;
PikeGjeografike * _vendndodhja;
public:
Aeroport(string emri, PikeGjeografike * vendndodhja);
Aeroport(string emri, double gjeresia, double gjatesia);
string merrEmri() const;
PikeGjeografike * merrVendndodhjen() const;
};
Kodi PHP:
// Klasa për të prezantuar një Fluturim
class Fluturim {
private:
Aeroport * _vendnisja;
Aeroport * _vendarritja;
public:
Fluturim(Aeroport * vendnisja, Aeroport * vendarritja);
Aeroport * merrVendnisja() const;
Aeroport * merrVendarritja() const;
int merrDistancen() const;
};
Kodi PHP:
// Klasa për leximin e një skedari me aeroportët
class AeroportParser {
public:
// lexon nje istream dhe kthen një map<emri, aeroporti> me aeroporte
static map<string, Aeroport *> parseAeroportet(istream & teDhenat);
};
Kodi PHP:
// Klasa për leximin e një skedari me fluturimet
class ParseFluturimet {
public:
// lexon nje istream dhe kthen një liste/vektor me fluturime
static vector<Fluturim *> parseFluturimet(istream & teDhenat);
};
Kodi PHP:
// Klasa për veprimet elementare për shtimin, fshirjen, dhe gjetjen e
// aeroporteve
class AeroportetDAO {
private:
// mund të jetë vektor, map, ose një burim të dhënash (data source)
// e lidhur me databazën
map<string, Aeroport *> * _aeroportet;
public:
AeroportetDAO();
AeroportetDAO(map<string, Aeroport *> aeroportet);
// Shton aeroportin e dhenë në databazë
void shtoAeroportin(Aeroport * aeroport);
// Fshin Aeroportin e dhënë nga databaza
void fshiAeroportin(Aeroport * aeroport);
// Kthen Aeroportin me emrin e dhënë ose NULL nëse nuk ekziston
Aeroport * gjejAeroportin(string emri);
};
Kodi PHP:
// AeroportManager Përdor AeroportetDAO për të plotësuar kërkesat
// biznesit/klientit për aeroportet.
class AeroportetManager {
private:
AeroportetDAO * _aeroportetDAO;
public:
AeroportetManager(AeroportetDAO * aeroportetDAO);
// Ngarkon aeroportet nga skedari i dhene. Perdor AeroportParser
// për të lexuar aeroportet dhe i shton ata në AeroportetDAO.
void ngarkoAeroportet(string & skedari);
// Kthen Aeroportin me emrin e dhënë ose NULL nëse nuk ekziston
Aeroport * gjejAeroportin(string & emri);
};
Kodi PHP:
// Klasa për veprimet elementare për shtimin, fshirjen, dhe gjetjen e
// fluturimeve
class FluturimetDAO {
private:
// mund të jetë vektor, map, ose një burim të dhënash (data source)
// e lidhur me databazën
vector<Fluturim> * _fluturimet;
public:
// Krijon FluturimetDAO pa fluturime
FluturimetDAO();
// Krijon FluturimetDAO me fluturimet e dhënë
FluturimetDAO(vector<Fluturim> * fluturimet);
// Shton fluturimin e dhenë në databazë
void shtoFluturimin(Fluturim * fluturim);
// Fshin fluturimin e dhënë nga databaza
void fshiFluturimin(Fluturim * fluturim);
// Kthen fluturimin nga vendnisja te vendarritja nëse ekziston; NULL në
// të kundërt
Fluturim * gjejFluturim(Aeroport * vendnisja, Aeroport * vendarritja);
// Kthen një vektor me të gjithë fluturimet
vector<Fluturim *> gjejTeGjitheFluturimet();
// Gjej fluturimet nga vendnisja.
// Kthen fluturimet e gjetur ose një vektor bosh.
vector<Fluturim *> gjejFluturimetNisurNga(Aeroport * vendnisja);
// Gjej fluturimet nga vendarritja
// Kthen fluturimet e gjetur ose një vektor bosh.
vector<Fluturim *> gjejFluturimetArrijneNe(Aeroport * vendarritja);
// metoda të tjera të ngjashme me të mësipërmet
...
};
Kodi PHP:
// Kjo është klasa kryesore që do plotësojë kërkesat e biznesit/klientit.
// Disa prej detyrave ia delegon AeroportManager-it dhe FluturimetDAO-s.
class FluturimetManager {
private:
AeroportManager * _aeroportManager;
FluturimetDAO * _fluturimetDAO;
public:
FluturimetManager(AeroportetDAO * aeroportetDAO,
FluturimetDAO * fluturimetDAO);
//---------
// metoda që ia delegon AeroportManager-it
void ngarkoAeroportet(string & skedari);
//---------
// metoda që ia delegon FluturimetDAO-s
vector<Fluturim *> merrTeGjitheFluturimet();
vector<Fluturim *> gjejFluturimetNisurNga(Aeroport * vendnisja);
vector<Fluturim *> gjejFluturimetArrijneNe(Aeroport * vendarritja);
//---------
// metoda qe i kryen me ndihmën e FluturimetDAO-s
Fluturim * shtoFluturimTeRastesishem();
vector<Fluturim *> shtoFluturimePerTeGjitheAeroportet();
// Ngarkon aeroportet nga skedari i dhene. Perdor FluturimetParser
// për të lexuar fluturimet dhe i shton ata në FluturimetDAO.
vector<Fluturim *> ngarkoFluturimetNgaSkedari(string & skedari);
//--------
// Metoda që i kryen me ndihmën e FluturimetDAO-s. Këto metoda
// mund t'i delegojë edhe tek një klasë tjetër e quajtur
// FluturimAnalizues
vector<Fluturim *> gjejLidhjenMeTeShkurterNga(Aeroport * vendnisja);
vector<Fluturim *> gjejLidhjenMeTeShkurterPerNe(Aeroport * vendarritja);
vector<Fluturim *> meTeShkurterQePershkon(vector<Aeroport *> aeroportet);
vector<Fluturim *> meTeShkurterQePershkonTeGjithe();
};
U mundova të ndiqja sintaksën e C++ të cilën kam ca kohë pa e përdour kështu që me siguri do ketë gabime, por prandaj ke përpiluesin.
Nuk do kishte vlerë detyra për ty nëse do shkruaja më shumë kod se kaq. Shpresoj të të ketë ndihmuar shpjegimi më lart. Nëse ke mundësi, do kisha dëshirë ta hidhje kodin e plotë në forum kur ta mbarosh për të parë nëse të ka ndihmuar dizajni im.
I mirëpres komentet apo kritikat nga profesionistët për dizajnin apo kodin e mësipërm; të argumentuara sigurisht, se ndryshe s'do kishin vlerë.
Krijoni Kontakt