问题描述
任何人都可以用简单的示例解释命令模式吗?我尝试在互联网上搜索,但我感到困惑.
推荐答案
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(); } }); } }
我个人不太喜欢命令.根据我自己的经验,它们仅适用于框架回调.
如果有帮助,请在隐喻意义上考虑命令;训练有素的士兵由他/她的指挥官命令,并按需士兵执行此命令.
其他推荐答案
您可以将命令模式工作流如下.
client 调用调用 => 调用调用 concretecommand => concretecommand 调用接收器方法,实现摘要命令方法.
uml图来自 dofactory 文章:
关键特征:
-
命令声明所有命令的接口,提供一个简单的execute()方法,该方法要求命令的接收器执行操作.
-
接收者知道要执行请求的方法.
-
调用持有命令,可以通过调用执行方法来获得命令执行请求.
-
客户端创建 concretecommands ,并为命令设置接收器.
-
concretecommand 定义了动作和接收器之间的绑定.
-
当调用器呼叫执行 concretecommand 将在接收器上执行一个或多个动作.
代码段:
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
说明:
在此示例中,
- 命令接口定义execute()方法.
- oncommand IS concretecommand ,实现execute()方法.
- 接收器是一个接口,实施者必须为方法提供实现.
- 电视和 dvdplayer 是两种类型的接收器,将其传递给了诸如Oncommand.
- 调用包含命令.这是从接收器.
- 调用接收 oncommand - > nath 接收者(电视)执行此命令.
通过使用调用器,您可以打开电视和DVDPlayer.如果您扩展了此程序,也可以关闭电视和DVDPlayer.
您可以使用命令模式到
-
将命令的发件人和接收器解除
-
实施回调机制
-
实现撤消和重做功能
-
保持命令的历史
请看一下此 dzone 和 journaldev and wikipedia 文章.
源代码作为Wikipedia页面简单,清洁和自我解释.
您可以实现 undo 和 redo 如果您按照此文章
其他推荐答案
这是您可以用来了解命令模式如何工作的另一个示例,使用现实生活中的情况:您不能不使用命令模式从飞机到另一个地方到另一个地方!
如果您是一个经常旅行者,那么您所关心的就是客户从您所处的地方旅行.您不在乎飞行员将如何飞行飞机或将有哪个航空公司可用..您无法真正预测这一点.您想要的只是获取空中港口,并告诉他们带您到达目的地.
但是,如果您这样做,您对机场当局的命令将被嘲笑!他们需要您提供命令对象,这是您的票.尽管您不在乎哪种航空公司或哪种飞机类型(当您准备飞行时),您需要提供机票命令对象.机场官员需要检查您的命令(机票),以便他们可以验证它,如果是假货,请撤消它,如果他们犯了一个错误,请重做它(无需您完成预订过程) .
简而言之,他们希望在决定是否调用或执行您的命令之前完全控制您的命令(机票),这使航空公司(接收者)执行(将您放在飞机上并将您带到您的目的地) .
请注意,您的命令(您的票)已经有了接收器(航空公司)的信息,没有该信息,机场官员甚至首先都不会开始处理您的机票.
机场当局甚至可以开一些门票.他们可能会选择延迟我的票,让我经过我之后的人(在我的之前调用另一个人票)
这是代码:
[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 } }
问题描述
Can anyone explain with a simple example the Command Pattern? I tried searching on the internet, but I got confused.
推荐答案
public interface Command { public void execute(); }
For the most part, commands are immutable and contain instructions that encapsulate a single action that is executed on demand. You might also have a RuntimeCommand that accepts instructions upon execution, but this delves more into the Strategy or Decorator Patterns depending on the implementations.
In my own opinion, I think it's very important to heed the immutable context of a command otherwise the command becomes a suggestion. For instance:
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(); } }); } }
I personally don't really like commands. In my own experience, they only work well for framework callbacks.
If it helps, think of a command in a metaphorical sense; a trained soldier is given a command by his/her commanding officer, and on demand the soldier executes this command.
其他推荐答案
You can think of Command pattern workflow as follows.
Client calls Invoker => Invoker calls ConcreteCommand => ConcreteCommand calls Receiver method, which implements abstract Command method.
UML Diagram from dofactory article:
Key features:
Command declares an interface for all commands, providing a simple execute() method which asks the Receiver of the command to carry out an operation.
The Receiver has the knowledge of what to do to carry out the request.
The Invoker holds a command and can get the Command to execute a request by calling the execute method.
The Client creates ConcreteCommands and sets a Receiver for the command.
The ConcreteCommand defines a binding between the action and the receiver.
When the Invoker calls execute the ConcreteCommand will run one or more actions on the 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(); } }
output:
Switch on from TV Switch on from DVDPlayer
Explanation:
In this example,
- Command interface defines execute() method.
- OnCommand is ConcreteCommand, which implements execute() method.
- Receiver is an interface and implementers have to provide implementation for the methods.
- TV and DVDPlayer are two types of Receivers, which are passed to ConcreteCommand like OnCommand.
- Invoker contains Command. It's the key to de-couple Sender from Receiver.
- Invoker receives OnCommand -> which calls Receiver (TV) to execute this command.
By using Invoker, you can switch on TV and DVDPlayer. If you extend this program, you switch off both TV and DVDPlayer too.
You can use Command pattern to
Decouple the sender & receiver of command
Implement callback mechanism
Implement undo and redo functionality
Maintain a history of commands
Have a look at this dzone and journaldev and Wikipedia articles.
Source code as Wikipedia page is simple, cleaner and self explanatory.
You can implement Undo and Redo if you follow the steps as quoted in this article
其他推荐答案
Here is another example you can use to understand how command pattern works, using real life scenarios: You cannot travel from one place to another by airplane without using the command pattern!
If you are a frequent traveler, all you care about as a client is to travel from where you are to another . you don't care about how the pilot will fly the plane or which airline will be available .. you cant really predict that. all you want is to get the the air port and tell them to take you to your destination.
But if you do that, your command to the airport authorities will be laughed at! they need you to supply a command object, which is your ticket. as much as you don't care about which airline or which plane type, when you are ready to fly, you need to supply a ticket command object. The invoker, which is the airport officials needs to check your command (ticket) so that they can validate it, undo it if it is fake, redo it if they made a mistake (without you having to go through the booking process all over).
In short , they want to have complete control of your command (ticket) before deciding whether or not to invoke or execute your command, which lets the airline (the receiver ) execute ( put you on a plane and take you to your destination) .
Mind you, your command (your ticket) already has the information of the receiver (airline) without which the airport officials wont even start to process your ticket in the first place.
The airport authorities could even have a bunch of tickets they are working on. they may choose to delay my ticket and let someone that came after me go through (invoke another persons ticket before mine)
Here is the 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 } }