Ho una libreria, che invia e riceve una serie di messaggi binari e li analizza.
Finora ho usato l'ereditarietà per il mio design, cioè
class BaseMsg
{
// init msg from rx'd binary stream
virtual bool fromBinary(std::vector<char> b) = 0;
// write msg content to binary stream to tx
virtual std::vector<char> toBinary() const = 0;
MsgType type;
};
class MsgA : public BaseMsg
{
MsgA()
{
type = MsgType::A;
}
bool fromBinary(std::vector<char> b)
{
// parse binary stream here and init members
}
std::vector<char> toBinary() const
{
// encode members to binary stream here
}
private:
std::string freetext;
// more members
};
class MsgB : public BaseMsg
{
MsgB()
{
type = MsgType::B;
}
bool fromBinary(std::vector<char> b)
{
// parse binary stream here and init members
}
std::vector<char> toBinary() const
{
// encode members to binary stream here
}
private:
double latitude;
double longitude;
// more members
};
Inoltre ho una classe di messaggistica Messenger
, che ha metodi per inviare e ricevere, cioè
bool sendMessage(std::unique_ptr<BaseMsg> msg)
{
std::vector<char> bin = msg->toBinary();
// send bin
}
std::unique_ptr<BaseMsg> receive(std::vector<char> receivedBinaryStream)
{
if (/*check in binary stream, if msg is MsgA*/)
{
auto msg = std::make_unique<MsgA>();
msg->fromBinary(receivedBinaryStream);
return std::move(msg);
}
if (/*check in binary stream, if msg is MsgB*/)
{
auto msg = std::make_unique<MsgB>();
msg->fromBinary(receivedBinaryStream);
return std::move(msg);
}
}
Funziona abbastanza bene, ma quando uso la libreria finisco per lanciare molto dalla classe base a una sottoclasse specifica. Questo è specialmente dopo la ricezione di un messaggio e l'utilizzo del messaggio nella mia applicazione.
//
auto msg = messenger.receive(binStream);
if (msg->type == MsgType::A)
{
// cast to MsgA and continue processing
}
else if (msg->type == MsgType::B)
{
// cast to MsgB and continue processing
}
Quindi la domanda è, se esiste un'architettura / design alternativo, che eviti i cast nell'ultimo esempio di codice.
La domanda non riguarda i dettagli dell'implementazione, ma se c'è un design migliore rispetto all'utilizzo dell'ereditarietà.
modifica
I messaggi hanno parametri diversi, ad es. MsgA fornisce testo libero, MsgB fornisce informazioni sulla posizione di un oggetto, ecc.
Pertanto, quando un messaggio viene utilizzato dall'applicazione, viene trasmesso alla sottoclasse per ottenere i parametri specifici del tipo.