Frage

Kann man erklären, mit einfachem Beispiel von Command-Mustern. Ich beziehe mich in Internet, aber ich habe verwirrt.

War es hilfreich?

Lösung

public interface Command {
   public void execute();
}

Für den größten Teil, sind Befehle, unveränderlich und enthalten Anweisungen, die eine einzelne Aktion einkapseln, die bei Bedarf ausgeführt wird. Sie können auch eine RuntimeCommand haben, die Anweisungen bei der Ausführung akzeptiert, aber das in die Strategie vertieft oder Decorator Patterns in Abhängigkeit von den Implementierungen.

In meiner eigenen Meinung, ich denke, es ist sehr wichtig, den unveränderlichen Kontext eines Befehls ansonsten wird der Befehl ein Vorschlag wird zu beachten. Zum Beispiel:

public final class StopServerCommand implements Command {
    private final Server server;

    public StopServerCommand(Server server) { this.server = server; }

    public void execute() {
        if(server.isRunning()) server.stop();
    }
}

public class Application {
    //...
    public void someMethod() {
        stopButton.addActionListener(new ActionListener() {
            public void actionPerformed(Event e) {
                 stopCommand.execute();
            }
        });
    }
}

ich persönlich nicht wirklich wie Befehle. In meiner eigenen Erfahrung, sie arbeiten nur gut für Rahmen Rückrufe.

Wenn es hilft, denken Sie an einen Befehl im übertragenen Sinne; ein ausgebildeter Soldat einen Befehl von seinem / ihrem Kommandanten gegeben wird, und auf Wunsch führt der Soldat diesen Befehl.

Andere Tipps

Sie können denken Befehlsmuster Workflow wie folgt.

Client Anrufe Invoker => Invoker Anrufe ConcreteCommand => ConcreteCommand Anrufe Empfänger Methode, die abstrakt implementiert Befehl Methode.

UML-Diagramm dofactory Artikel:

Key Features:

  1. Befehl eine Schnittstelle für alle Befehle erklärt, eine einfache Methode execute () bereitstellt, die den Empfänger des Befehls fragt eine Operation auszuführen.

  2. Die Empfänger hat das Wissen von dem, was die Anforderung zu tun durchzuführen.

  3. Die Invoker einen Befehl hält und bekommen die Befehl eine Anforderung zur Ausführung durch die Ausführungs Methode aufrufen.

  4. Die Client schafft ConcreteCommands und setzt ein Empfänger für den Befehl.

  5. ConcreteCommand definiert eine Bindung zwischen der Aktion und dem Empfänger.

  6. Wenn die Invoker Anrufe führen Sie die ConcreteCommand läuft eine oder mehrere Aktionen auf dem Receiver.

Code-Snippet:

interface Command {
    void execute();
}
interface Receiver {
    public  void switchOn();

}
class OnCommand implements Command{
    private Receiver receiver;

    public OnCommand(Receiver receiver){
        this.receiver = receiver;
    }
    public void execute(){
        receiver.switchOn();
    }
}
class Invoker {
    private Command command;

    public Invoker(Command command){
        this.command = command;
    }
    public void execute(){
        this.command.execute();
    }
}

class TV implements Receiver{

     public void switchOn(){
        System.out.println("Switch on from TV");
    }
}
class DVDPlayer implements Receiver{

    public void switchOn(){
         System.out.println("Switch on from DVDPlayer");
    }
}

public class CommandDemoEx{
    public static void main(String args[]){
        // On command for TV with same invoker 
        Receiver receiver = new TV();
        Command onCommand = new OnCommand(receiver);
        Invoker invoker = new Invoker(onCommand);
        invoker.execute();

        // On command for DVDPlayer with same invoker 
        receiver = new DVDPlayer();
        onCommand = new OnCommand(receiver);
        invoker = new Invoker(onCommand);
        invoker.execute();            
    }
}

Ausgabe:

Switch on from TV
Switch on from DVDPlayer

Erklärung:

In diesem Beispiel

  1. Befehl Schnittstelle definiert execute() Methode.
  2. OnCommand ist ConcreteCommand , die execute() Methode implementiert.
  3. Empfänger ist eine Schnittstelle und Implementierer haben die Implementierung der Methoden zur Verfügung zu stellen.
  4. TV und DVDPlayer gibt zwei Arten von Empfänger , die übergeben werden, wie OnCommand ConcreteCommand.
  5. Invoker enthält Befehl . Es ist der Schlüssel zu entkoppeln Sender von Empfänger .
  6. Invoker erhält OnCommand . -> welche Anrufe Empfänger (TV) diesen Befehl auszuführen

Durch die Verwendung von Fragesteller können Sie auf TV und DVDPlayer wechseln. Wenn Sie dieses Programm verlängern, schalten Sie Sie beide TV und DVDPlayer zu.

Sie können Befehl Muster

  1. entkoppeln den Absender und Empfänger des Befehls

  2. Callback-Mechanismus implementieren

  3. Implementieren Undo und Redo-Funktionalität

  4. eine Geschichte von Kommandos pflegen

Haben Sie einen Blick auf diese dzone und journaldev und Wikipedia Artikel.

Der Quellcode als Wikipedia-Seite ist einfach, saubere und selbsterklärend.

können Sie implementieren Rückgängig und Wiederherstellen , wenn Sie die Schritte, wie sie in diesem Artikel

Hier ist ein weiteres Beispiel, das Sie verstehen können, wie Befehlsmuster arbeitet, das wirkliche Leben Szenarien: Sie können nicht von einem Ort zum anderen mit dem Flugzeug reisen, ohne den Befehl Muster mit

Wenn Sie häufig reisen, alles, was Sie über Pflege als ein Client zu reisen, von wo aus man zu einem anderen sind. Sie kümmern sich nicht darum, wie der Pilot das Flugzeug fliegen oder die Fluggesellschaft zur Verfügung stehen wird .. man kann nicht wirklich vorhersagen. alles, was Sie wollen, ist das der Luftkanal zu bekommen und ihnen sagen, Sie zu Ihrem Ziel zu nehmen.

Aber wenn Sie das tun, Ihr Befehl an die Flughafenbehörden wird bei ausgelacht werden! sie benötigen Sie einen Befehl Objekt zu liefern, die Ihr Ticket ist. so viel wie Sie nicht über die Fluggesellschaft oder das Flugzeugtyp egal, wenn Sie bereit zu fliegen ist, müssen Sie ein Ticket Befehlsobjekt liefern. Die Aufrufer, die der Flughafen benötigt Beamte Ihren Befehl (Ticket) zu überprüfen, so dass sie es überprüfen kann, rückgängig gemacht werden, ob es eine Fälschung ist, es wiederholen, wenn sie einen Fehler gemacht (ohne dass Sie überall durch den Buchungsprozess gehen) .

Kurz gesagt, wollen sie die vollständige Kontrolle über Ihren Befehl haben (Ticket), bevor sie entscheidet, ob Ihr Befehl aufzurufen oder auszuführen, die die Fluggesellschaft können (Empfänger) ausführen (setzen Sie auf einer Ebene und bringen Sie zu Ihrem Ziel) .

Wohlgemerkt, Ihr Befehl (Ticket) hat bereits die Informationen des Empfängers (Fluggesellschaft), ohne die die Flughafenbeamten nicht sogar beginnen Sie Ihr Ticket in erster Linie zu verarbeiten.

Die Flughafenbehörden könnten sogar ein paar Tickets haben sie gerade arbeiten. sie können wählen, mein Ticket zu verzögern und lassen Sie jemand, der nach mir gehen durchkam (andere Personen Ticket vor meinen aufrufen)

Hier ist der Code:

 [TestClass]
    public class Client
    {
        [TestMethod]
        public void MyFlight_UsingCommandPattern()
        {
            var canadianAirline = new Airline();

            AirlineTicket_Command myTicket = new MyAirLineTicket(canadianAirline);

            var airportOfficials = new AirportOfficials_Invoker(myTicket);
            airportOfficials.ProcessPasengerTicket_And_AllowPassengerToFly_Execute();

            //assert not implemented
        }
    }

    public class AirportOfficials_Invoker
    {
        private AirlineTicket_Command PassengerTicket { set; get; }

        public AirportOfficials_Invoker(AirlineTicket_Command passengerTicket)
        {
            throw new NotImplementedException();
        }

        public void ProcessPasengerTicket_And_AllowPassengerToFly_Execute()
        {
            PassengerTicket.Execute();
        }
    }

    public abstract class AirlineTicket_Command
    {
        protected Airline Airline { set; get; }

        protected AirlineTicket_Command(Airline airline)
        {
            Airline = airline;
        }

        public abstract void Execute();
    }

    public class MyAirLineTicket : AirlineTicket_Command
    {
        public MyAirLineTicket(Airline airline)
            : base(airline)
        {
        }

        public override void Execute()
        {
            Airline.FlyPassenger_Action();
        }
    }

    public class Airline
    {
        public void FlyPassenger_Action()
        {
//this will contain all those stuffs of getting on the plane and flying you to your destination
        }
    }

Meine Forderung ist eine Folge von Aufgaben zu erfüllen (die wiederverwendet in mehreren Usecases werden kann), die jeweils mit einer eigenen Ausnahme fließen. Gefunden Befehlsmuster Implementierung logischer hier.

Ich versuche es wie jede Aktion durch den Befehl ausgeführt zu machen (ob normal / alternative Strömung) kann auch einen Ausnahmehandler sein. Wenn jedoch der Befehl mit einem anderen Handler registriert wird, dann sollten diese verwendet werden. Irgendwelche Vorschläge für eine Verbesserung / Korrektur sind willkommen.

public interface Command {
    Result run() throws Exception;
    Command onException(ExceptionHandler handler);
}

public class Result {
}

public interface ExceptionHandler {
    void handleException(Exception e);
}

public interface Action {
    Result execute() throws Exception;
}

public class BasicCommand implements Command {
private Action action;
private ExceptionHandler handler;

public BasicCommand(Action action) {
    if (action == null) {
        throw new IllegalArgumentException("Action must not be null.");
    }
    this.action = action;
    this.handler = (ExceptionHandler) this.action;
}

@Override
public Command onException(ExceptionHandler handler) {
    if (handler != null) {
        this.handler = handler;
    }
    return this;
}

public Result run() throws Exception {
    Result result = null;
    try {
        result = action.execute();
    } catch (Exception e) {
        handler.handleException(e);
    }
    return result;
}

}

public class BasicAction implements Action, ExceptionHandler {
    private Object[] params;


    public BasicAction(Object... params) {
        this.params = params;
    }

    @Override
    public Result execute() throws Exception {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void handleException(Exception e) {
        // TODO exception translation: prepare unchecked application. exception and throw..
    }
}

public class Main {

    public static void main(String[] args) throws Exception {
        int param1 = 10;
        String param2 = "hello";

        // command will use the action itself as an exception handler
        Result result = new BasicCommand(new BasicAction(param1, param2)).run();

        ExceptionHandler myHandler = new ExceptionHandler(){
            @Override
            public void handleException(Exception e) {
                System.out.println("handled by external handler");
            }
        };
        // command with an exception handler passed from outside.
          Result result2 = new BasicCommand(new BasicAction(param1, param2)).onException(myHandler).run();

    }
}

Befehl Design Patterns abkoppelt Aufrufer von Service und Anbieter von Service. Im allgemeinen Szenario sagen für z. B. Wenn Object A Dienst Object B will, wird es direkt B.requiredService() aufrufen. Somit wird ein bewusst über B. in der Anwendung Command Muster ist, wird diese Kopplung entfernt. Hier gibt es ein Zwischenobjekt als Command bekannt, die ins Bild kommt. So A beschäftigt sich mit Command Objekt und Befehlsobjekt behandelt aktuelle Objekt B. Dieser Ansatz hat mehrere Anwendungen, wie die Gestaltung von Anwendungen, die da sind: -

  • akzeptiert Befehle als Anforderungen.
  • Undoing Anfragen.
  • Anfragen Anfragen.
  • Erstellen von Makros.
  • Erstellen von Aufgaben Testamentsvollstrecker und Task-Manager.

Für weitere Informationen über, Befehl, Design, Muster, werde ich empfehlen https: //en.wikipedia. org / wiki / Command_pattern . Für alle anderen Entwurfsmuster finden Sie unter https: // www.u-cursos.cl/usuario/.../mi_blog/r/head_first_design_patterns.pdf

Ich würde versuchen Sie eine andere grobe Analogie zu geben.

Nehmen wir an, dass eines Tages Gott auf dich anruft und sagt, dass die Welt in Gefahr und er Ihre Hilfe, um es retten muss. Weitere Sie helfen, sagt er, dass er einige Superhelden auf der Erde gesandt hat.

Da er nicht weiß, oops und daher nicht nennt er sie nicht superhelden ( bietet keine Ihnen eine Schnittstelle oder eine abstrakte Klasse über sie ), sondern nur sagen, ihre Namen für die Ex - batman , superman, Eisenmann und die Kräfte, die sie haben.

Er sagt auch, dass in Zukunft könnte er mehr solche Leute in Zukunft senden.

Jetzt Er weist Ihnen besondere Verantwortung -> sie kontrollieren und dafür liefert Ihnen sieben Hände . Er behebt nicht die Aufgabe, jede Hand selbst, sondern überlässt es auf Ihnen.

Sie wollen Flexibilität in jede Handsteuerung eines jeden Superhelden Macht zuweisen und wollen nicht immer wieder Dinge durch mehrere Bedingungen ändern.

Sie sind in einer Lösung. Was tun Sie jetzt?

Geben Sie Command-Muster.

Erstellen Sie eine Schnittstelle Befehl und hat nur eine Methode execute () darin. jede Leistung jeden Superhelden kapselt und dass Kommando für ex machen implementieren - IronManCreatesSuitCommand

Jetzt können Sie jede Hand auf jeden Befehl jederzeit zuweisen Sie viel mehr Flexibilität, weil jetzt keine Ihrer Hände kümmert sich um die spezifische Aufgabe, es zu tun hat. Sie können es nur einen Befehl zuweisen zu. Er fordert ausführen darauf und der Befehl kümmert sich um alles andere.

Jetzt auch wenn Gott anderen Superhelden mit unterschiedlichen Leistungen sendet, wissen Sie, was zu tun ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top