Rappresentazione di dati gerarchici (C ++)

3

Supponiamo di avere 2 classi: account e contatti come questo:

class Account {
    string Id;
    string Name;
}

class Contact {
    string Id;
    string FirstName;
    string LastName;
}

Un account può contenere molti contatti. Questi dati sono gestiti in una classe "DataManager" che funge da repository per il resto del programma. Ci sono 2 requisiti principali:

  • Per un account, ho bisogno di recuperare un elenco dei suoi contatti
  • Per un dato accountId o contactId ho bisogno di recuperare il rispettivo account / contatto. Il recupero di un contatto dovrebbe funzionare, anche se non so a quale account è stato assegnato il contatto. In questo modo

    Contatti c = dataManager.GetContact (contId);

Ho discusso con un collega le seguenti 2 opzioni per implementare la relazione Account-Contatto in C ++:

Opzione 1: archivia gerarchicamente ... la classe Account conterrà una mappa di contatti. La chiave di quella mappa sarebbe il ContactId. Il DataManager memorizzerebbe una mappa di account:

class DataManager {
    Account& GetAccount(string accountId);
    Contact& GetContact(string contactId);

    map<string, Account> accounts;
}
class Account {
    map<string, Contact> contacts;

    Contact& GetContact(string contactId);
    list<reference_wrapper<Contact>> GetContacts();
}

Problema: l'implementazione di DataManager :: GetContact dovrebbe essere ripetuta su tutti i contatti dell'account. In alternativa, potrei memorizzare una mappa di contactId - > accountId in DataManager per trasferire rapidamente l'account che contiene il contatto richiesto.

Opzione 2: "Archiviazione piatta" In questa soluzione, gli oggetti sono tutti memorizzati nel DataManager. La classe account memorizza solo Id dei suoi contatti.

class DataManager {
    map<string, Account> accounts;
    map<string, Contact> contacts;

    Account& GetAccount(string accountId);
    Contact& GetContact(string contactId);
}
class Account {
    map<string, string> contactIds;
    list<string> GetContactIds();
}

Problema: per ottenere un elenco di tutti i contatti di un account, il codice chiamante (- > in real: un codice nel DataManager) deve scorrere l'elenco di contactId recuperati dall'oggetto Account e raccogliere il rispettivo contatto oggetti dal DataManager.

Opzione 2.1 Riferimento wrapper Per quanto riguarda i contenitori che utilizzano reference_wrapper anziché string contactId? (come suggerito da @Caleth)

Che cosa fare? Quale di queste opzioni ti sembra più legittima? Oppure suggerisci una soluzione diversa?

    
posta Stefan Woehrer 15.03.2017 - 11:37
fonte

1 risposta

1

Suggerisco questo design:

class DataManager {
  map<string, Account> accounts;
  map<string, Contact*> contacts;
  Account& GetAccount(string accountId);
  Contact& GetContact(string contactId);
}
class Account {
  map<string, Contact*> contacts;
  list<Contact*> GetContactIds();
}

Quindi, puoi accedere direttamente ai contatti di un account.

Nota: è meglio utilizzare wrapper di riferimento come @Caleth ha commentato o punti di riferimento condivisi invece di puntatori di contatti non elaborati.

    
risposta data 15.03.2017 - 12:44
fonte

Leggi altre domande sui tag