Definition: In ein Objekt in ein Objekt in Einklang bringen, sodass Sie den Client mit verschiedenen Anforderungen, Warteschlangenanforderungen oder Aufzeichnungsanforderungsprotokollen parametrisieren und Befehlsrevokations- und Wiederherstellungsfunktionen bereitstellen.
Typ: Verhaltensmuster
Klassendiagramm:
Die Struktur des Befehlsmodus
Wie der Name schon sagt, ist der Befehlsmodus die Kapselung von Befehlen. Schauen wir uns zunächst die Grundstruktur im Befehlsmodusklassendiagramm an:
Befehlsklasse: ist eine abstrakte Klasse, die die Befehle erklärt, die ausgeführt werden müssen. Im Allgemeinen muss eine Ausführungsmethode an die Öffentlichkeit veröffentlicht werden, um den Befehl auszuführen.
CONCRETECOMMAND -Klasse: Die Implementierungsklasse der Befehlsklasse implementiert die in der abstrakten Klasse deklarierten Methoden.
Kundenklasse: Die endgültige Client -Rufklasse.
Die Funktionen der oben genannten drei Klassen sollten einfacher zu verstehen sein. Konzentrieren wir uns auf die Rechnungsklasse und die Recrevier -Klasse.
Invoker -Klasse: Der Anrufer ist dafür verantwortlich, Befehle aufzurufen.
Empfängerklasse: Der Empfänger ist dafür verantwortlich, Befehle zu empfangen und auszuführen.
Um es unverblümt auszudrücken, die sogenannte Kapselung von Befehlen ist nichts anderes, als eine Reihe von Operationen in eine Methode zu schreiben und dann vom Kunden aufgerufen zu werden. Es spiegelt sich im Klassendiagramm wider. Es benötigt nur eine konkrete Kurs- und Client -Klasse, um die Einkapselung von Befehlen abzuschließen. Selbst wenn es weiter geht, kann eine Befehlsklasse für eine angemessene Abstraktion hinzugefügt werden, um die Flexibilität zu erhöhen. Was ist die Funktion dieses Anrufers und Empfängers?
Tatsächlich können Sie aus einer anderen Perspektive nachdenken: Wenn Sie einige Operationen einfach als Befehl für andere zusammenfassen, wie kann es als Muster bezeichnet werden? Als Verhaltensmodell muss der Befehlsmodus zunächst eine geringe Kopplung erreichen. Nur wenn der Kopplungsgrad niedrig ist, kann die Flexibilität verbessert werden. Der Zweck des Hinzufügens der Anrufer- und Empfängerrollen ist genau dafür.
Beispiel:
Die Simulation des Betriebs des Fernsehgeräts beinhaltet die Befehle für Einschalt-, Herunterfahren und Wechsel. Der Code ist wie folgt
// Schnittstelle zur Ausführung des Befehls für öffentliche Schnittstelle {void execute (); } // Befehls Empfängerempfänger öffentlicher Klasse TV {public int currentChannel = 0; public void Turnon () {System.out.println ("Der Televisino ist auf."); } public void turnoff () {System.out.println ("Der Fernseher ist aus."); } public void changechannel (int kanal) {this.currentChannel = Kanal; System.out.println ("Now TV -Kanal ist" + Kanal); }} // Befehl concreteCommand public class Commandon implementiert Befehl {private tv mytv; public commandon (tv tv) {mytv = tv; } public void execute () {mytv.Turnon (); }} // Befehl concreteCommand public class Commandoff implementiert Befehl {private tv mytv; public Commandoff (TV TV) {mytv = tv; } public void execute () {mytv.Turnoff (); }} // Channel Switching Command ConcreteCommand Public Class CommandChange Implements Command {private tv mytv; privater Int -Kanal; public CommandChange (TV TV, int Channel) {mytv = tv; this.channel = Channel; } public void execute () {mytv.changechannel (Kanal); }} // Es kann als Remote Control Invoker Public Class Control {private Command OnCommand, Offcommand, Changechannel; öffentlicher Steuerelement (Befehl ein, Befehl aus, Befehlskanal) {onCommand = on; offcommand = off; Changechannel = Kanal; } public void Turnon () {onCommand.execute (); } public void turnoff () {offcommand.execute (); } public void changechannel () {changechannel.execute (); }} // Klassen Client Public Class Client {public static void main (String [] args) {// Befehlsempfängerempfänger tv mytv = new tv (); // Power-On-Befehl ConcreteCommond Commandon on = New Commandon (myTV); // STRADDOWN -Befehl ConcreteCommond Commandoff off = new Commandoff (myTV); // Channel Switching Command ConcreteCommond CommandChange Channel = new commandChange (mytv, 2); // Befehlskontrollobjekt Invoker Control Steuerelement = Neue Steuerung (Ein, Aus, Kanal); // Power-on Control.Turnon (); // Channel Control.changechannel (); // steuerung steuern.turnoff (); }}Ausführungsergebnisse
Der Televisino ist an. Jetzt ist der Fernsehkanal 2, der Fernseher ist aus.
Vor- und Nachteile des Befehlsmodus
Zunächst ist der Befehlsmodus eine sehr Kapselung: Jeder Befehl ist eingekapselt, und für den Client wird der entsprechende Befehl so viel aufgerufen, wie die Funktion benötigt wird, ohne zu wissen, wie der Befehl ausgeführt wird. Beispielsweise gibt es eine Reihe von Befehlen der Dateioperation: Erstellen Sie eine neue Datei, kopieren Sie eine Datei und löschen Sie eine Datei. Wenn diese drei Operationen in eine Befehlsklasse eingekapselt sind, muss der Client nur wissen, dass es diese drei Befehlsklassen gibt. Was die in der Befehlsklasse eingefasste Logik betrifft, muss der Client es nicht wissen.
Zweitens hat der Befehlsmodus eine gute Skalierbarkeit. Im Befehlsmodus, die grundlegendste Einkapselung von Operationen in der Empfängerklasse und die sekundäre Kapselung dieser Grundvorgänge der Befehlsklasse. Beim Hinzufügen neuer Befehle ist das Schreiben der Befehlsklasse im Allgemeinen nicht von Grund auf neu. Es gibt eine große Anzahl von Empfängerklassen für Anrufe, und es gibt auch eine große Anzahl von Befehlsklassen für Anrufe, und der Code ist sehr wiederverwendbar. Zum Beispiel müssen wir bei der Operation einer Datei einen Befehl hinzufügen, um eine Datei zu schneiden, und müssen nur die beiden Befehle zum Kopieren einer Datei und zum Löschen einer Datei kombinieren, die sehr bequem ist.
Lassen Sie uns schließlich über die Nachteile des Befehlsmodus sprechen, dh wenn es viele Befehle gibt, wird es Kopfschmerzen zur Entwicklung sein. Insbesondere viele einfache Befehle sind nur wenige Codezeilen, die implementiert werden müssen. Wenn Sie den Befehlsmodus verwenden, müssen Sie sich keine Sorgen darüber machen, wie einfach der Befehl ist, müssen Sie eine Befehlsklasse schreiben, um ihn zu verkapulieren.
Anwendbare Szenarien für den Befehlsmodus
Für die meisten Funktionen zur Response-Modus ist es besser geeignet, den Befehlsmodus zu verwenden. Wie in der Befehlsmodus -Definition lautet, ist der Befehlsmodus bequemer für die Implementierung von Funktionen wie Protokollierung und Rückgängigungsvorgängen.
Zusammenfassen
Es ist eine sehr verwickelte Frage für alle Entwickler, den Modus zu verwenden. Manchmal wird aufgrund der vorausschauenden Änderungen der Anforderungen ein bestimmtes Entwurfsmuster für die Flexibilität und Skalierbarkeit des Systems verwendet, diese vorhersehbare Anforderung jedoch nicht. Im Gegenteil, es sind viele unvorhersehbare Anforderungen erhoben, was dazu geführt hat, dass das Designmuster bei der Änderung des Codes die entgegengesetzte Rolle spielte, so dass sich das gesamte Projektteam beschwerte. Ich glaube, jeder Programmierer hat auf ein solches Beispiel gestoßen. Basierend auf dem Prinzip der agilen Entwicklung, wenn wir Programme entwerfen, sollten wir es nicht vorstellen, wenn wir sie gut lösen können, ohne ein bestimmtes Muster nach den aktuellen Bedürfnissen zu verwenden, da es nicht schwierig ist, ein Designmuster einzuführen. Wir können es auf dem System tun, wenn wir es wirklich brauchen, um es zu verwenden und dieses Designmuster einzulegen.
Nehmen Sie als Beispiel den Befehlsmodus. In unserer Entwicklung ist die Funktion des Request-Response-Modus sehr häufig. Im Allgemeinen werden wir den Antwortvorgang in die Anforderung in eine Methode zusammenfassen. Diese eingekapselte Methode kann als Befehl bezeichnet werden, jedoch nicht als Befehlsmodus. Ob dieses Design auf die Höhe des Musters angehoben werden sollte, muss separat berücksichtigt werden, denn wenn der Befehlsmodus verwendet wird, müssen die beiden Rollen von Anrufer und Empfänger eingeführt werden. Die ursprünglich an einem Ort platzierte Logik ist in drei Kategorien verteilt. Beim Entwerfen ist es notwendig zu prüfen, ob diese Kosten es wert sind.