java 使用命令设计模式

cxfofazt  于 2023-04-04  发布在  Java
关注(0)|答案(6)|浏览(166)

有没有人能用一个简单的例子解释一下命令模式?我试着在网上搜索,但我搞糊涂了。

dzhpxtsq

dzhpxtsq1#

public interface Command {
   public void execute();
}

在大多数情况下,命令是不可变的,并且包含封装了按需执行的单个操作的指令。您也可能有一个在执行时接受指令的RuntimeCommand,但这需要根据实现深入研究策略或装饰模式。
在我自己看来,我认为注意命令的不可变上下文非常重要,否则命令就变成了一个建议。例如:

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();
            }
        });
    }
}

我个人并不喜欢命令,根据我的经验,它们只适合框架回调。
如果有帮助的话,可以从隐喻的Angular 来思考一个命令;受过训练的士兵由他/她的指挥官给出命令,并且士兵根据要求执行该命令。

mrzz3bfm

mrzz3bfm2#

您可以将命令模式的工作流程想象为如下。

  • Client* calls Invoker =〉Invoker calls ConcreteCommand =〉ConcreteCommand calls Receiver method,实现抽象的 Command 方法。

代码片段:

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();            
    }
}

输出:

Switch on from TV
Switch on from DVDPlayer

说明:
在这个例子中,
1.命令接口定义execute()方法。
1.OnCommandConcreteCommand,实现execute()方法。
1.Receiver是一个接口,实现者需要提供方法的实现。
1.TVDVDPlayer是两种类型的Receiver,和OnCommand一样传递给ConcreteCommand。
1.Invoker包含Command,是实现Sender与Receiver解耦合的关键。
1.Invoker接收OnCommand-〉,调用Receiver(TV)执行此命令。
通过使用Invoker,你可以打开电视和DVD播放器。如果你扩展这个程序,你也可以关闭电视和DVD播放器。
您可以使用Command模式
1.解耦合命令的发送者和接收者
1.实现回调机制

5t7ly7z5

5t7ly7z53#

下面是另一个示例,您可以使用它来了解命令模式的工作原理,使用真实的生活场景:如果不使用命令模式,你就不能乘飞机从一个地方到另一个地方!
如果你是一个经常旅行的人,作为一个客户,你所关心的就是从你所在的地方旅行到另一个地方。你不关心飞行员将如何驾驶飞机或哪家航空公司将可用。你真的无法预测。你所想要的就是得到机场,并告诉他们带你到你的目的地。
但是如果你这样做,你对机场当局的命令会被嘲笑!他们需要你提供一个命令对象,也就是你的机票。尽管你不关心哪个航空公司或哪种飞机类型,但当你准备飞行时,你需要提供一个机票命令对象。调用者,也就是机场官员需要检查你的命令(票),以便他们可以验证它,撤销它,如果它是假的,重做它,如果他们犯了一个错误(没有你必须通过整个预订过程)。
简而言之,他们希望在决定是否调用或执行您的命令之前完全控制您的命令(机票),这让航空公司(接收方)执行(将您送上飞机并带您前往目的地)。
提醒你一下,你的命令(你的机票)已经有了接收者(航空公司)的信息,没有这些信息,机场官员甚至不会开始处理你的机票。
机场当局甚至可能有一堆他们正在处理的机票。他们可能会选择延迟我的机票,让我之后的人通过(在我之前调用另一个人的机票)
下面是代码:

[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
        }
    }
ie3xauqp

ie3xauqp4#

我的要求是执行一系列任务(可以在多个用例中重用),每个任务都有自己的异常流。
我试图让它像命令执行的每个动作(无论是正常/交替流)也可以是一个异常处理程序.然而,如果命令是注册与另一个处理程序,那么这应该被使用.任何改进/更正的建议是受欢迎的.

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();

    }
}
fkaflof6

fkaflof65#

命令设计模式将服务的调用者和服务的提供者解耦。在一般情况下,例如,如果Object A想要Object B的服务,它将直接调用B.requiredService()。因此,A知道B。在命令模式中,这种耦合被移除。这里,有一个称为Command的中间对象,它进入画面。因此,A处理Command对象,命令对象处理实际对象B。这种方法有几个应用,例如设计应用程序,它们是:

  • 接受命令作为请求。
  • 撤消请求。
  • 请求请求
  • 正在创建宏。
  • 创建任务执行器和任务管理器。

有关命令设计模式的更多信息,我推荐https://en.wikipedia.org/wiki/Command_pattern

wj8zmpe1

wj8zmpe16#

我想在这里再给你一个粗略的类比。
假设有一天,上帝召唤你,告诉你世界正处于危险之中,他需要你的帮助来拯救它,他告诉你他已经派了一些超级英雄到地球上来。
因为他不知道哎呀,因此他不叫他们超级英雄(不提供任何接口或抽象类在他们),但只是告诉你他们的名字前 bat 侠,超人,钢铁侠和他们的权力。
他还说,将来他可能会派更多这样的人来。
现在他给你特别的责任---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
你想要灵活地分配任何超级英雄的力量的任何手控制,并且不想通过多种条件重复改变事情。
你陷入困境了,你现在怎么办?
输入命令模式。
创建一个接口Command,里面只有一个方法execute()。封装每个超级英雄的所有能力,并使其实现前IronManCreatesSuitCommand的Command
现在你可以在任何时候给任何手分配任何命令,这给了你更多的灵活性,因为现在你的手都不关心它必须做的特定任务。你只需要给它分配任何命令。它调用执行,命令会处理其他一切。
现在,即使上帝派了其他拥有不同力量的超级英雄,你也知道该怎么做。

相关问题