Using Command Design Pattern

Using Command Design pattern

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.

Using Command- Pattern to create an object and add this to an ArrayList

Firstly, I think you should understand how the design pattern works and how the classes interact with each other. You can see an example here https://refactoring.guru/design-patterns/command.

My way of doing it:

Command.java

// concrete commands will implement this interface
// you can also use an abstract class if you want to have certain attributes, such as a TicketSystem
public interface Command {
// this method can be set to return something useful instead of void, if needed
void execute();
}

AddTicketCommand.java

public class AddTicketCommand implements Command {
// TicketSystem and Ticket attributes

// constructor that initializes the attributes

@Override
public void execute() {
// add the Ticket to the TicketSystem
}
}

Invoker.java

public class Invoker {
private Command command;

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

public void invoke() {
command.execute();
}
}

Therefore, when you want to use a certain command, you set it with accordingly. For example: invoker.setCommand(new AddTicketCommand(new TicketSystem(), new Ticket())) and then call it with invoker.invoke().

Hope it helped!

Design pattern for command line software with multiple functionalities

Because this is a command line application, I think the Command pattern could be useful for you. Personally, I believe this is a good way to structure console apps.

This is a possible implementation (in c#) to support multiple commands:

// The main class, the entry point to the program
internal class Program
{
private static void Main(string[] args)
{
var p = new Processor();
p.Process(args);
}
}

/* The command processor class, its responsibility is to take its input parameters to create the command and execute it. */
public class Processor
{
private CommandFactory _commandFactory;

public Processor()
{
_commandFactory = new CommandFactory();
}

public void Process(string[] args)
{
var arguments = ParseArguments(args);
var command = _commandFactory.CreateCommand(arguments);

command.Execute();
}

private CommandArguments ParseArguments(string[] args)
{
return new CommandArguments
{
CommandName = args[0]
};
}
}

/* Creates a command based on command name */
public class CommandFactory
{
private readonly IEnumerable<ICommand> _availableCommands = new ICommand[]
{
new Command1(), new Command2(), .....
};

public ICommand CreateCommand(CommandArguments commandArguments)
{
var result = _availableCommands.FirstOrDefault(cmd => cmd.CommandName == commandArguments.CommandName);
var command = result ?? new NotFoundCommand { CommandName = commandArguments.CommandName };
command.Arguments = commandArguments;

return command;
}
}

public interface ICommand
{
string CommandName { get; }
void Execute();
}

/* One of the commands that you want to execute, you can create n implementations of ICommand */
public class Command1 : ICommand
{
public CommandArguments Arguments { get; set; }

public string CommandName
{
get { return "c1"; }
}

public void Execute()
{
// do whatever you want to do ...
// you can use the Arguments
}
}

/* Null object pattern for invalid parametters */
public class NotFoundCommand : ICommand
{
public string CommandName { get; set; }

public void Execute()
{
Console.WriteLine("Couldn't find command: " + CommandName);
}
}

Command Design Pattern - Execute method with return value

Since the Invoker can change Commands at runtime, there must be loose type safety. For cases where you know the command's return value, you can pass its return type to execute():

command_w_return

using System;

class Receiver {
public bool someAction() {
return false;
}

public string someAction2() {
return "some action value";
}

public void voidAction() {
Console.WriteLine("void action");
}
}

interface ICommand {
object doAction();
};

class ConcreteCommand : ICommand {
private Receiver receiver;

public ConcreteCommand(Receiver recv) {
receiver = recv;
}

public object doAction() {
return receiver.someAction();
}
}

class ConcreteCommand2 : ICommand {
private Receiver receiver;

public ConcreteCommand2(Receiver recv) {
receiver = recv;
}

public object doAction() {
return receiver.someAction2();
}
}

class VoidCommand : ICommand {
private Receiver receiver;

public VoidCommand(Receiver recv) {
receiver = recv;
}

public object doAction() {
receiver.voidAction();
return true;
}
}

class Invoker {
private ICommand command;

public void setCommand(ICommand cmd) {
command = cmd;
}

public T execute<T>() {
return (T) command.doAction();
}
}

public class Program
{
public static void Main()
{
Invoker i = new Invoker();
Receiver r = new Receiver();

i.setCommand(new ConcreteCommand(r));
Console.WriteLine(i.execute<bool>());

i.setCommand(new ConcreteCommand2(r));
Console.WriteLine(i.execute<string>());

i.setCommand(new VoidCommand(r));
i.execute<object>();

ICommand[] commands = new ICommand[] {
new ConcreteCommand(r),
new ConcreteCommand(r),
new ConcreteCommand2(r),
new ConcreteCommand2(r),
new VoidCommand(r)
};

foreach (ICommand c in commands) {
i.setCommand(c);
Console.WriteLine(i.execute<object>());
}
}
}
False
some action value
void action
False
False
some action value
some action value
void action
True

Difference between Strategy pattern and Command pattern

Typically the Command pattern is used to make an object out of what needs to be done -- to take an operation and its arguments and wrap them up in an object to be logged, held for undo, sent to a remote site, etc. There will tend to be a large number of distinct Command objects that pass through a given point in a system over time, and the Command objects will hold varying parameters describing the operation requested.

The Strategy pattern, on the other hand, is used to specify how something should be done, and plugs into a larger object or method to provide a specific algorithm. A Strategy for sorting might be a merge sort, might be an insertion sort, or perhaps something more complex like only using merge sort if the list is larger than some minimum size. Strategy objects are rarely subjected to the sort of mass shuffling about that Command objects are, instead often being used for configuration or tuning purposes.

Both patterns involve factoring the code and possibly parameters for individual operations out of the original class that contained them into another object to provide for independent variability. The differences are in the use cases encountered in practice and the intent behind each pattern.

Command pattern vs reflection

  1. first way is better, use reflections only when don't have other options.
  2. in one application there should be one approach to solve one kind of problem.
  3. I think the first approach is fine. (much better then if/else blocks)

Design pattern for accepting terminal commands

Introduce a common command interface and use a Map

Map<String, Command> commands = new HashMap<String, Command>();
commands.put("myCommand1", new MyCommand());
commands.put("myCommandN", new MyCommandN());

JCommander cmd = new JCommander();
cmd.addCommand("myCommand1", cmd1);
...
cmd.addCommand("myCommandN", cmdN);
try {
cmd.parse(args);

Command command = commands.get(cmd.getParsedCommand());
if(command == null){
cmd.usage();
}
// execute command
}
...


Related Topics



Leave a reply



Submit