This is the 9th day of my participation in the August More Text Challenge
Command mode is not something that many of you might use, but it’s interesting. In command mode, operations and data can be packaged into objects, facilitating the system to manage and maintain commands.
UML class diagrams location: www.processon.com/view/link/6…
This article is linked to: github.com/shidawuhen/…
Definition 1.
1.1 Command Mode
Command pattern: Encapsulates a request as an object, allowing you to parameterize clients with different requests; Queue or log requests, and support undoable operations.
UML:
1.2 analysis
The above definitions and UML are complex and may be difficult for you to understand.
First we need to understand what a command is. Commands include instructions and data. Instructions are actions, and data affects instructions. If 3 meters forward, forward is an instruction, 3 meters is data.
Then let’s look at what each class means.
Command and ConcreteCommand are commands with Excute functions that represent actions to be performed.
ConcreteCommand calls Excute(), and finally calls the Action of the Receiver. This means that the ConcreteCommand is just a container, and the real operation logic is in the Receiver.
The Invoker contains all the commands that control when the Command executes Excute().
Now let’s simplify UML, leaving out Invoker and Receiver, and see if it’s easy to understand.
With this concise version of UML, let’s look at why the command pattern is used.
Commands include instructions and data. Instructions actually correspond to operations, and operations correspond to functions in code.
In fact, the command mode is to encapsulate the function as an object, the system can perform various operations on the object, such as queuing execution, logging, undo and so on.
Why wrap functions as objects? C, C++, and Go support function Pointers, but not all languages do, and command mode comes into play. And even if the language supports function Pointers, there is still a problem with how to store the data part of a command.
Therefore, the Command mode is to package the request into a Command object, store it, and the system will process it according to the actual demand.
2. Application scenarios
You may feel that the command mode is the same as MQ or factory mode, but it is different in detail:
-
MQ contains only data, not behavior, and command mode contains both
-
Factory mode requires real-time execution, but command mode can be stored and executed later
Command mode I’ve never used before. Beauty in Design Patterns describes a common architecture for game development: client requests are stored by a server, which has a separate thread to process them. So let’s write the code according to this scenario.
3. Code implementation
package main
import "fmt"
/** * @author: Jason Pang * @description: Command interface */
type Command interface {
Execute()
}
/** * @author: Jason Pang * @description: Move command */
type MoveCommand struct {
x, y int64
}
/** * @author: Jason Pang * @description: How to move * @receiver m */
func (m *MoveCommand) Execute(a) {
fmt.Printf("Move %d to the right, move %d \n up", m.x, m.y)
}
/** * @author: Jason Pang * @description: Attack command */
type AttackCommand struct {
skill string
}
/** * @author: Jason Pang * @description: How to attack @receiver a */
func (a *AttackCommand) Execute(a) {
fmt.Printf("Use skill %s\n", a.skill)
}
/** * @author: Jason Pang * @description: Record Command * @param action * @return Command */
func AddCommand(action string) Command {
if action == "attack" {
return &AttackCommand{
skill: "Savage Collision.",}}else { // The default is move
return &MoveCommand{
x: 10,
y: 20,}}}func main(a) {
// Record the command
lc := make([]Command, 0)
lc = append(lc, AddCommand("attack"))
lc = append(lc, AddCommand("move"))
lc = append(lc, AddCommand("move"))
lc = append(lc, AddCommand("attack"))
// Execute the command
for _, c := range lc {
c.Execute()
}
}
Copy the code
Output:
➜ myproject go run main.go
Use the ability to brutalize
We went 10 to the right, we went 20 up
We went 10 to the right, we went 20 up
Use the ability to brutalize
From the above code, you should be able to understand the command pattern. It can be seen that different commands are generated for different requests, which contain corresponding data and operations. This is also what the schema definition says about “queuing or logging requests, and supporting undoable actions”.
conclusion
Design patterns are designed to solve real-world problems, and we need to tie them to concrete scenarios. When solving problems, it doesn’t matter whether standard design patterns are used or not. Patterns are only means, and means need to serve the purpose.
The last
If you like my article, you can follow my public account (Programmer Malatang)
My personal blog is shidawuhen.github. IO /
Review of previous articles:
-
Design patterns
-
recruitment
-
thinking
-
storage
-
The algorithm series
-
Reading notes
-
Small tools
-
architecture
-
network
-
The Go