Command mode application example
Pattern structure
The command mode contains the following primary roles.
- Abstract Command role: Declares the interface to execute commands and has the abstract method execute() to execute commands.
- Concrete Command role: A Concrete implementation class of an abstract Command class, which owns the receiver object and performs the operations to be performed by the Command by invoking the receiver’s functions.
- Implementer/Receiver: Performs operations related to command functions and is the real implementer of specific command object services.
- Invoker (Invoker) role: is the sender of the request, it usually has a number of command objects, and accesses the command object to perform the request, it does not directly access the receiver.
Let’s start with a simple example: giving a command to a robot
Let’s create an object
/ * * *@authorNaruto *@email huanghao@haioupai.com
* @date 2021/4/6
* @describeRobot command abstraction */
interface RobotCommand {
fun execute(a)
}
Copy the code
Specific commands
/ / dance
class DanceCommand(robot:Robot):RobotCommand {
private varrobot:Robot? =null
init {
this.robot=robot
}
override fun execute(a){ robot? .dance() } }/ / hug
class HugCommand(robot:Robot):RobotCommand {
private varrobot:Robot? =null
init {
this.robot=robot
}
override fun execute(a){ robot? .hug() } }/ / kiss
class KissCommand(robot:Robot):RobotCommand {
private varrobot:Robot? =null
init {
this.robot=robot
}
override fun execute(a){ robot? .kiss() } }/ / sleep
class SleepCommand(robot:Robot):RobotCommand {
private varrobot:Robot? =null
init {
this.robot=robot
}
override fun execute(a){ robot? .sleep() } }Copy the code
The requester
/ * * *@authorNaruto *@email huanghao@haioupai.com
* @date 2021/4/6
* @describe* /
class User:RobotCommand {
private var cmds= mutableListOf<RobotCommand>()
/ * * *@UpdateDate: 2021/4/6 assembling of *@Description: Adds a command *@Author: naruto * /
fun add(command: RobotCommand){
cmds.add(command)
}
/ * * *@UpdateDate: 2021/4/6 over *@Description: Clear all commands *@Author: naruto * /
fun clear(a){
cmds.clear()
}
override fun execute(a) {
for(index in cmds){
index.execute()
}
}
}
Copy the code
The implementer
class Robot(name:String) {
fun kiss(a){
println("Start kissing...")}fun hug(a){
println("Start hugging...")}fun dance(a){
println("Start dancing...")}fun sleep(a){
println("Start sleeping with...")}}Copy the code
Unit test a wave
class ExampleUnitTest {
@Test
fun paly(a) {
val user=User()
val robot=Robot("Little beauty") // A robot named Meiuser.add(DanceCommand(robot)) user.add(HugCommand(robot)) user.add(KissCommand(robot)) user.add(SleepCommand(robot)) User.execute ()}} Result: Start dancing... Start hugging... Start kissing... Start sleeping with... Process finished with exit code0
Copy the code
Conclusion:
The main advantages of command mode are as follows.
- Reduce the coupling degree of the system by introducing middleware (abstract interface).
- Good scalability, easy to add or delete commands. Adding and deleting commands in command mode does not affect other classes and meets the open/Close principle.
- Macro commands can be implemented. Command mode can be combined with composite mode to assemble multiple commands into a composite command, known as a macro command.
- Easy to implement Undo and Redo operations. The command mode can be combined with the memo mode to realize command undo and restore.
- You can add additional functionality to existing commands. For example, logging, combined with the decorator pattern is more flexible.
Its disadvantages are:
- A large number of concrete command classes can be generated. Because each specific operation requires the design of a specific command class, this adds complexity to the system.
- The result of the command pattern is actually the result of the recipient’s execution, but in order to architecture in the form of commands and decouple requests from implementation, the introduction of additional type structures (requester and abstract command interface) makes it more difficult to understand. However, this is a common problem with design patterns. Abstraction inevitably increases the number of classes, and code abstraction is more difficult to understand than code aggregation.