Ich habe eine Menge Schlüssel und Werte, die ich an unsere Nachrichtenwarteschlange senden möchte, indem wir sie in ein Byte-Array packen. Ich werde ein Byte-Array aller Schlüssel und Werte machen, die immer weniger als 50K sein sollten und dann an unsere Nachrichtenwarteschlange senden.
Paketklasse :
%Vor% Unten ist die Art, wie ich Daten sende. Ab sofort erlaubt mein Design nur das asynchrone Senden von Daten durch den Aufruf von sendToQueueAsync
method in der obigen sendData()
Methode.
Jetzt muss ich mein Design erweitern, damit ich Daten auf drei verschiedene Arten senden kann. Es liegt am Benutzer zu entscheiden, auf welche Art er Daten senden will, entweder "sync" oder "async".
sender.sendToQueueAsync
method. sender.sendToQueueSync
method. sender.sendToQueueSync
method aufruft. In diesem Fall muss ich irgendwie socket
Variable übergeben, damit sendData
von dieser Variable weiß. SendRecord-Klasse :
%Vor%Anrufer rufen nur eine der folgenden drei Methoden auf:
Wie soll ich meine Packet
und SendRecord
Klasse entwerfen, damit ich Packet
class sagen kann, dass diese Daten auf eine der drei oben genannten Arten an meine Nachrichtenwarteschlange gesendet werden müssen. Der Benutzer muss entscheiden, auf welche Weise er Daten an die Nachrichtenwarteschlange senden möchte. Ab jetzt, wie meine Packet
Klasse strukturiert ist, kann sie Daten nur auf eine Art senden.
Ich denke, Ihre beste Option ist das Strategie-Muster ( Ссылка ).
Mit diesem Muster können Sie das Verhalten jedes Typs von "send" kapseln, z. B. eine AsynchronousSend-Klasse, eine SynchronousSend-Klasse und eine AsynchronousSocketSend-Klasse. (Sie könnten wahrscheinlich bessere Namen finden). Die Klasse Packet
kann dann basierend auf einer Logik entscheiden, welche Klasse verwendet werden soll, um die Daten an die Warteschlange zu senden.
Ich sehe die Definition von sender
in Packet
nicht. Ich nehme an, dass es als private Instanzvariable definiert ist?
Das Design muss in der Tat repariert werden.
Wenn die Packet
-Klasse das Senden durchführt, verstößt das Design gegen das Prinzip der einheitlichen Verantwortlichkeit . Es sollte eine separate (möglicherweise abstrakte) Klasse geben, die die zu sendenden Daten vorbereitet (bereitet eine java.nio.Buffer
-Instanz vor) und sie kann eine oder mehrere Unterklassen haben, von denen eine eine java.nio.ByteBuffer
-Instanz zurückgibt.
Eine separate Klasse, die ein Buffer
erhält und das Senden durchführt. Diese (möglicherweise abstrakte) Klasse kann Unterklassen für die verschiedenen sendenden Plattformen und Methoden haben.
Dann benötigen Sie eine andere Klasse, die das Builder-Muster implementiert. Clients, die Pakete senden möchten, verwenden den Builder, um konkrete Packet
und Sender
(und möglicherweise andere erforderliche Eigenschaften wie eine Socket-Nummer) anzugeben, und rufen dann send()
auf, das das Senden durchführt.
Sie könnten eine enum-Klasse haben, sagen wir PacketTransportionMode, bei der eine 'send' -Methode für verschiedene Arten von Enum-Werten überschrieben werden würde (SYNC, ASYNC, SYNC_ON_SOCKET), Beispiel:.
%Vor%Außerdem muss in der Paketklasse die Variable transportationMode eingeführt werden. In der Implementierung von packet.send () kann this.packetTransportationMode.send (this)
aufgerufen werdenDer Client kann ein Paketobjekt erstellen und seinen transportationMode am Anfang einstellen, ähnlich wie bei RecordPartition. Dann kann der Client packet.send ();
aufrufenOder anstatt die transportationMode-Variable innerhalb der Paketklasse zu setzen und this.packetTransportationMode.send (this) aufzurufen, kann der Client auch ein Packet-Objekt erstellen und PacketTransportionMode.SYNC.send (packet) direkt aufrufen.
Zuerst müssen Sie eine klare Antwort auf die Frage haben, wer (oder welcher Teil Ihres Codes) verantwortlich ist für die Entscheidung, welche Methode verwendet werden soll.
(Nur um ein paar Möglichkeiten zu nennen)
Die Antwort bestimmt, welche Struktur am besten geeignet ist.
Dennoch ist es klar, dass die aktuelle sendData()
-Methode der Ort ist, an dem die Entscheidung in Kraft tritt. Daher muss diese Methode bereitgestellt werden, um die Implementierung zu verwenden. Die tatsächliche send()
Wahrscheinlichkeit ist in allen Fällen ähnlich. Es wird vorgeschlagen, die Funktionalität sending in eine Schnittstelle zu kapseln, die die Methodensignatur send()
bereitstellt:
Wenn der Ziel-Socket aus den tatsächlichen Nachrichtendaten bestimmt werden soll, bevorzugen Sie möglicherweise eine allgemeine Signatur von
%Vor% und machen Sie diesen Socket-Wert optional oder verwenden Sie einen bestimmten Wert für die Codierung "keine spezifischen Socket" Fälle. Andernfalls könnten Sie eine bestimmte Sender
-Instanz verwenden, bei der der Socket über Konstruktor übergeben wurde.
Ich sehe derzeit keinen gültigen Grund für die von Ihnen zur Verfügung gestellten Aufrufe, die drei verschiedenen Sendemethoden als drei verschiedene Methoden innerhalb einer Klasse zu implementieren. Wenn gemeinsamer Code ein Grund ist, ermöglicht die Verwendung einer gemeinsamen Basisklasse eine angemessene Freigabe.
Damit bleibt die Frage, wie die spezifische Instanz der entsprechenden Sender
Implementierung in sendData()
zur Verfügung gestellt werden soll.
Soll die sendende Strategie außerhalb von sendData()
ermittelt werden, muss die Implementierung übergeben werden. Entweder als Parameter oder als Feld aus der aktuellen Klasseninstanz. Wenn die lokalen Daten die sendende Strategie bestimmen, sollten Sie die Bestimmung der richtigen Implementierung an eine Selektionsklasse delegieren, die die korrekte Implementierung zurückgibt. Der Anruf sieht dann ähnlich aus:
Obwohl es kein klareres Bild davon gibt, was festgelegt ist und was bei der Ausführung variabel ist, ist es schwierig, best approach zu empfehlen.
Falls die Entscheidung auf Daten basiert, ist der gesamte Auswahl- und Umleitungsprozess lokal für Packet
class.
Wenn die Entscheidung extern zu Packet
getroffen wird, möchten Sie vielleicht eine sendende Strategie-Implementierung an diesem Ort bekommen und diese als Parameter nach unten in addAndSendJunked()
(oder genauer gesagt bis zu sendData()
) übergeben.
Verwenden Sie enum varibale zum Definieren der Typen der Nachricht senden
%Vor%Strategie. Der Unterschied zu Kerri Browns Antwort ist, dass Packet keine Entscheidungen zwischen Strategien treffen sollte. Entscheiden Sie stattdessen außerhalb der Paketklasse.
Die Schnittstelle für einzelne sendende Strategien sollte von drei verschiedenen Klassen implementiert werden, die jeweils einem der genannten sendenden Ansätze entsprechen. Inject Strategie-Schnittstelle in das Paket, so dass Packet nicht ändern muss, unabhängig davon, welche Strategie es behandelt.
Sie sagten, dass es auf der Wahl des Benutzers basieren muss. So können Sie den Benutzer im Voraus fragen, was die Wahl ist, und dann basierend darauf die Implementierung einer sendenden Strategie-Schnittstelle instanziieren, die der Wahl des Benutzers entspricht. Instanziieren Sie dann das Paket mit der ausgewählten sendenden Strategie-Instanz.
Wenn Sie glauben, dass die spätere Wahl nicht vom Benutzer abhängt, dann machen Sie das zu einer Fabrik. So wird Ihre Lösung zu einer Kombination aus Fabrik und Strategie.
In diesem Fall kann Packet die Factory-Schnittstelle injizieren. Das Paket fragt die Factory nach der Sendungsstrategie. Als nächstes sendet es mit der von der Fabrik erworbenen Strategie. Factory fragt nach Benutzereingaben, die später ersetzt werden können, indem eine Auswahl basierend auf einer anderen Bedingung getroffen wird und nicht die Benutzereingabe. Dies erreichen Sie, indem Sie die Factory-Schnittstelle in Zukunft anders implementieren und diese neue Fabrik anstelle dieser einspeisen (d. H. Fabrik mit Benutzereingabe statt mit einer anderen auf Bedingungen basierenden Fabrik).
Beide Ansätze geben Ihnen einen Code, der dem Open / Close-Prinzip folgt. Aber versuchen Sie nicht zu übertreiben, wenn Sie keine Fabrik brauchen.
Tags und Links java design-patterns oop bytebuffer srp