2017-07-16 1 views
0

ich die Antworten auf diese Frage sah: Design pattern for handling multiple message typesDesign für mehrere Nachrichtentypen, aber Subklassen alle das gleiche tun

und ich bin in einem ähnlichen Boot. Der Unterschied, den ich habe, ist, dass ich ein existierendes Protobuf-Schema verwende, das ich nicht ändern kann. Das Protobuf-Schema verfügt über die Eigenschaft messageType. Der generierte Code sieht aus wie

TradeMessage.parseFrom(byte[] bytes) 
OtherMessage.parseFrom(byte[] bytes) 
AnotherMessage.parseFrom(byte[] bytes) 

So jetzt ich eine Fabrik Muster haben, dass, wenn eine Nachricht im Empfänger kommt

MessageReceiver.java 

Object parser = messageParserFactory.getParser(messageType); 

die Art der Parser Get

MessageParserFactory.java 

public MessageParser getParser(int messageType) { 
    if (messageType = Constants.TRADE_MESSAGE) { 
     return new TradeParser(); 
    } else if (messageType = Constants.OTHER_MESSAGE) { 
     return new OtherParser(); 
    } 
    return null; 
} 

Grundsätzlich wiederholt arbeiten für alle verschiedenen Nachrichtentypen, die im Wesentlichen nur die generierte parseFrom-Methode umbrechen.

public interface MessageParser { 
    void doParse(byte[] bytes); 
} 

TradeParser.java 
public void doParse(byte[] bytes) { 
    TradeParser.parseFrom(bytes); 
} 

OtherParser.java 
public void doParse(byte[] bytes) { 
    OtherParser.parseFrom(bytes); 
} 

AnotherParser.java 
public void doParse(byte[] bytes) { 
    AnotherParser.parseFrom(bytes); 
} 

Es funktioniert, aber gibt es einen besseren Weg, um alle da im Grunde die Parser ich für jeden Nachrichtentyp erstellen Sie genau die gleiche Sache und rufen Sie einfach parseFrom.

+0

Benötigen Sie den 'MessageParser' überhaupt? Warum geben Sie nicht einfach die geparste Instanz zurück? –

+1

'messageType =' sollte 'messageType ==' sein. Ich nehme an, das ist nur ein bisschen Pseudocode? – Michael

+0

Geben Sie auch nicht 'null' zurück, wenn es sich um einen nicht unterstützten Nachrichtentyp handelt, werfen Sie eine Ausnahme aus. – Michael

Antwort

0

Haben Sie jemals eine große Anzahl von Nachrichtentypen? Sind Ihre Nachrichten komplex?

In jedem Fall sehe ich, warum Sie vielleicht denken, dass es unnötig ist, wie Sie Ihre parseFrom-Methode im Moment gerade wickeln. Es könnte interessant werden, wenn Ihr Parsen komplex wird und nicht nur ein Aufruf der parseFrom-Methode.

Wäre es für Sie im Moment nicht das Beste, ein Schlüssel/Wert-Array mit dem Nachrichtentyp als Schlüssel und dem Wert Klasse als zu speichern und dann Ihre Nachricht mithilfe der Reflektion zu instanziieren?

Ich denke, das könnte ziemlich sauber sein, wie Sie Ihr Array in einer Context/Config-Datei definieren können.

+0

Die Anzahl der Nachrichtentypen ist kleiner als 20. Ich sehe nicht viel Logik in den Parsern, außer das Parsen der Nachrichten. Die Logik ist in einem anderen Bereich der App. – Crystal

+0

Wie würde ich das mit Reflektion machen? Gibt es irgendwelche Leistungseinbußen, da jedes Mal, wenn eine Nachricht von einem Client kommt, dieses Recht nach unten gehen müsste, um den messageParser zu erhalten. – Crystal

+0

Ja, es gibt erhebliche Leistungskosten, die durch Reflexion instanziiert werden. Ich nahm jedoch an, dass Ihre parseFrom-Methoden wahrscheinlich statisch waren und ich glaube, dass Aufrufe von statischen Methoden weniger kostspielig sind. Wäre nicht in der Lage, sich an die Quelle zu erinnern, also nimm diese Aussage mit Vorsicht oder besser, teste sie! In der Logik müssten Sie Ihr Array durchsuchen, die mit Ihrem Nachrichtentyp verknüpfte Klasse abrufen und dann einen Aufruf an Ihr parseFrom mit Reflektion vornehmen. Es wird etwa so aussehen: Methode m = clazz.getMethod ("name", argTypes); Objekt o = method.invoke (null, args); – Maaaatt

Verwandte Themen