Sto lavorando con un semplice protocollo binario. Ogni pacchetto è composto da 10 byte. Il primo byte specifica il tipo di pacchetto. Ci sono molti (~ 50) tipi di pacchetti usati.Separazione del parser e del gestore del protocollo in Java
Voglio scrivere un parser generale per questo protocollo che è indipendente dalla gestione dei pacchetti. Quindi il parser dovrebbe rilevare il tipo di pacchetto e inserire i dati in un'istanza della classe di pacchetto appropriata, che contiene i dati del protocollo. Ad esempio, considerando le classi sottostanti: Quando il parser rileva il tipo di pacchetto 1 -> nuovo Tipo1() e legge i byte non elaborati e imposta la temperatura e l'umidità. Allo stesso modo per il tipo di pacchetto 2 e tutti gli altri tipi di pacchetti.
class Packet {
byte[] raw;
}
class Type1 extends Packet {
int temperature;
int humidity;
}
class Type2 extends Packet {
DateTime sunrise;
DateTime sunset;
}
Poiché ci sono tanti tipi di pacchetti, ma ogni applicazione utilizza solo pochissime, dovrebbe essere possibile registrare per determinati tipi prima di analizzare inizio. Tutti gli altri tipi di pacchetti sono ignorati.
Sto pianificando di avere un PacketParser per ogni tipo di pacchetto. Probabilmente, ho bisogno anche di un corso per ogni tipo. Es .:
abstract class Type1Parser {
abstract void handle(Type1 packet);
}
class Type1Parser extends PacketParser {
//how to use/set handler? how to pass packet to handler?
static public Type1Handler type1Handler = null;
@override
void parse(Packet input) {
if(type1Handler == null)
return;
Type1 packet = new Type1(input);
packet.temperature = byteToInt(input.raw, 0, 3);
packet.humidity = byteToInt(input.raw, 4, 7);
type1Handler.handle(packet);
}
}
Come collegare parser e gestore? Sopra un approccio ingenuo: Il programma deve implementare Type1Handler e impostare la variabile statica Type1Parser.type1Handler.
Poi il parser principale può apparire come segue:
class MainParser {
Type1Parser type1 = new Type1Parser();
Type2Parser type2 = new Type2Parser();
...
void parse(byte[] packet) {
switch(packet[0]) {
case 1: type1.parse(packet); break;
case 2: type2.parse(packet); break;
...
}
}
}
Tuttavia, questo sembra essere 1) un sacco di linee molto simili di codice 2) un sacco di spese generali, dal momento che tutti parser pacchetto sono istanziati e per ogni pacchetto viene chiamato parse(), anche se non è registrato alcun gestore.
Qualche idea su come migliorare questo codice?
Nota: l'analisi deve essere trasparente per il programma. Il codice di analisi dovrebbe rimanere all'interno della "libreria di analisi". Quindi idealmente, il programma solo "conosce" le classi TypeXHandler e TypeX.
"per ogni pacchetto parse() viene chiamato, anche se non è registrato alcun gestore." - Sembra che sia necessario chiamare un parser, almeno, per ignorare i byte dei pacchetti nel flusso di input. È possibile leggere il tipo di pacchetto e saltare il resto dell'analisi semplicemente saltando la lunghezza del pacchetto (ho assunto che ogni tipo di pacchetto abbia una lunghezza fissa). –
Gestisce la porzione di codice a cui si desidera passare le informazioni sui pacchetti? Cosa si suppone di fare? – NESPowerGlove
Per sbarazzarsi di * alcune * ripetizioni in 'parse' non si potrebbe fare' parser PacketParser; 'usare l'interruttore per determinare e impostare il parser, e poi fuori dal commutatore fare' parser.parse (pacchetto); '? So che non è profondo ma riduce il verbatim. – ChiefTwoPencils