Как правильно реализовать класс содержащий коллекции объектов?

Надо реализовать класс содержащий коллекции объектов. Мне надо чтоб там был функционал добавления объектов, удаления, вывода на экран, поиск по параметру (по коду). Но не понимаю как правильно это спроектировать.

class Registry {
 
private:
 
    vector<Patient> patients;
    vector<Doctor> doctors;
    vector<Appointment> appointments;
 
public:
 
    Registry();
 
    ~Registry();
 
    const vector<Patient> &GetPatients() const;
 
    const vector<Doctor> &GetDoctors() const;
 
    const vector<Appointment> &GetAppointments() const;
 
    void SetPatients(vector<Patient> patients);
 
    void SetDoctors(vector<Doctor> doctors);
 
    void SetAppointments(vector<Appointment> appointments);
 
    void AddDoctor(string name, string surname, string qualification);
 
    void RemoveDoctor(vector<Doctor>::const_iterator itDoctor);
 
    void AddPatient(string name, string surname, string phone, int age);
 
    void RemovePatient(vector<Patient>::const_iterator itPatient);
 
    void AddAppointment(int year, int month, int day, int hour, int minute, vector<Patient>::const_iterator itPatient,
                        vector<Doctor>::const_iterator itDoctor);
 
    void RemoveAppointment(vector<Appointment>::const_iterator itAppointment);
 
    void ShowAll(const vector<Patient> &patientsVector);
 
    void ShowAll(const vector<Doctor> &doctorsVector);
 
    void ShowAll(const vector<Appointment> &appointmentsVector, const vector<Patient> &patientsVector,
                 const vector<Doctor> &doctorsVector);
 
    vector<Patient>::const_iterator FindByCode(const vector<Patient> &patientsVector, int code);
 
    vector<Doctor>::const_iterator FindByCode(const vector<Doctor> &doctorsVector, int code);
 
    vector<Appointment>::const_iterator FindByCode(const vector<Appointment> &appointmentsVector, int code);
 
};

Я думаю, что у меня плохо то, что например методы RemovePatient, RemoveDoctor и т.д не перегруженные, было бы наверно лучше сделать чтобы это был один перегруженный метод Remove. Но как мне это сделать если я в геттере возвращаю константную ссылку, и не могу потом ее менять. А если я буду возвращать просто по значению, то тогда мне надо будет брать через геттер этот вектор, удалять из него что мне надо методом Remove, и потом сеттером устанавливать в объект измененный вектор? Что-то я уже совсем запутался..


Ответы (1 шт):

Автор решения: DmitryK

Мысли вслух:
Не совсем понятно зачем вы в методы класса передаете ссылки на поля класса?
А геттеры нужны только для того, чтобы иметь доступ к данным объекта за пределами класса.
Также, хранить итераторы на Patient и Doctor в векторе Appointment - не самая здравая мысль. А если вы удалили доктора, а потом добавили нового? В итоге у вас операцию на глазах будет делать проктолог.
У пациентов и докторов должен быть какой-то уникальный идентификатор, по которому их искать и их же добавлять в Appointment. И это точно не итератор из вектора, т.к. итератор - это идентификатор места хранения объекта, а не самого объекта. Например можно в классах Patient и Doctor сделать статический счетчик. Или использовать хэш-функцию.
Если у вас класс Реестр, то он должен только хранить объекты. Объекты должны создаваться при помощи своих классов Patient и Doctor. Ну или написать фабричные функции.
Add() по идее должен принимать объект (ссылку) класса. Т.е. вы где-то создаете объект нужного класса, а потом добавляете его в регистр. Так же, как std::vector<> - он принимает объект класса и кладет его в нужную ячейку.

Add( Doctor& a){}
Add( Patient& a){}
Add( Appointment& a){}

Remove() также принимает либо ссылку на объект, который нужно удалить, либо ID.
Константные ссылки на вектора нужно возвращать только в случае, если вы собрались работать с ними за пределами класса - что не совсем правильно.

class Registry {
 
private:
 
    vector<Patient> patients;
    vector<Doctor> doctors;
    vector<Appointment> appointments;
    
    // физически удаляют объект из вектора
    void Remove(vector<Doctor>::iterator itDoctor);
    void Remove(vector<Patient>::iterator itPatient);
    void Remove(vector<Appointment>::iterator itAppointment);

    // находят в векторе нужный объект по коду
    vector<Patient>::iterator FindPatient(int code);
    vector<Doctor>::iterator FindDoctor(int code);
    vector<Appointment>::iterator FindAppointment(int code);

public:
    void Add( Doctor& a);
    void Add( Patient& a);
    void Add( Appointment& a); 

    void ShowAllPatients(void);
    void ShowAllDoctors(void);
    void ShowAllAppointments(void);
};

Ещё можно немножко аля "метапрограммирование" сделать. Например создать типы данных DoctorID, PatientID, AppointmentID (обертки) и на их основе перегружать методы.

struct DoctorID { int value; };
struct AppointmentID { int value; };
struct PatientID { int value; };

class Doctor
{
    DoctorID id;
    ....
};
class Registry 
{
    int Find(DoctorID id);
    int Find(PatientID id);
    int Find(AppointmentID id);
};
→ Ссылка