CommandDesignPattern
CommandDesignPattern
In command pattern, the request is send to the invoker and invoker pass it to
the encapsulated command object.
Command object passes the request to the appropriate method
of Receiver to perform the specific action.
The client program create the receiver object and then attach it to the
Command. Then it creates the invoker object and attach the command object
to perform an action.
Now when client program executes the action, it’s processed based on the
command and receiver object.
package com.journaldev.design.command;
void openFile();
void writeFile();
void closeFile();
}
package com.journaldev.design.command;
@Override
public void openFile() {
System.out.println("Opening file in unix OS");
}
@Override
public void writeFile() {
System.out.println("Writing file in unix OS");
}
@Override
public void closeFile() {
System.out.println("Closing file in unix OS");
}
package com.journaldev.design.command;
public class WindowsFileSystemReceiver implements
FileSystemReceiver {
@Override
public void openFile() {
System.out.println("Opening file in Windows OS");
@Override
public void writeFile() {
System.out.println("Writing file in Windows OS");
}
@Override
public void closeFile() {
System.out.println("Closing file in Windows OS");
}
Did you noticed the Override annotation and if you wonder why it’s used,
please read java annotations and override annotation benefits.
Now that our receiver classes are ready, we can move to implement our
Command classes.
We can use interface or abstract class to create our base Command, it’s a
design decision and depends on your requirement.
We are going with interface because we don’t have any default
implementations.
package com.journaldev.design.command;
void execute();
}
Now we need to create implementations for all the different types of action
performed by the receiver. Since we have three actions we will create three
Command implementations. Each Command implementation will forward the
request to the appropriate method of receiver.
package com.journaldev.design.command;
package com.journaldev.design.command;
package com.journaldev.design.command;
Invoker is a simple class that encapsulates the Command and passes the
request to the command object to process it.
package com.journaldev.design.command;
package com.journaldev.design.command;
Let’s move now to create our command pattern example client program that
will consume our file system utility.
package com.journaldev.design.command;
}
Notice that client is responsible to create the appropriate type of command
object. For example if you want to write a file you are not supposed to
create CloseFileCommand object.
Client program is also responsible to attach receiver to the command and then
command to the invoker class.
Output of the above command pattern example program is:
Underlying OS is:Mac OS X
Opening file in unix OS
Writing file in unix OS
Closing file in unix OS
Here is the class diagram for our file system utility implementation.
Command is the core of command design pattern that defines the contract for
implementation.
Receiver implementation is separate from command implementation.
Command implementation classes chose the method to invoke on receiver
object, for every method in receiver there will be a command implementation.
It works as a bridge between receiver and action methods.
Invoker class just forward the request from client to the command object.
Client is responsible to instantiate appropriate command and receiver
implementation and then associate them together.
Client is also responsible for instantiating invoker object and associating
command object with it and execute the action method.
Command design pattern is easily extendible, we can add new action
methods in receivers and create new Command implementations without
changing the client code.
The drawback with Command design pattern is that the code gets huge and
confusing with high number of action methods and because of so many
associations.