Golang命令模式

88 阅读2分钟

If you often use the Linux Command, a common command can kill the process we want, as shown below:


ps -ef | grep java | grep -v grep | awk '{print $2}' | xargs kill -9

The kill command does not directly terminate the process. The linux command is an input terminal calling program, which will call the linux kernel to terminate the process.

Now the Command Design Pattern is similar to Linux commands, and when we enter commands, the calling program will execute them. We can define the command rules for how the invoker calls.

We define the command rules:

commandcomment
lsshow all member names
choosechoose a member
selectshow member info
updateupdate member info

init the member info:

{"Lisa": 12, "Nick": 33, "Martin": 143, "Benjamin": 2, "John": 7}

we execute command as follow:

ls | choose John | select | update 0

it means: Show all member info, select john, show his information and update his information

command.go

package designpattern

import (
	"fmt"
	"strconv"
	"strings"
)

var mockChooseMap = map[string]int{"Lisa": 12, "Nick": 33, "Martin": 143, "Benjamin": 2, "John": 7}

type Command interface {
	exec(command string) string
}

type LsCommand struct {
}

type SelectCommand struct {
}

type UpdateCommand struct {
}

type ChooseCommand struct {
}

func (ls *LsCommand) exec(command string) string {
        fmt.Printf("exec command: %s\n", command)
	keys := make([]string, 0, len(mockChooseMap))
	for k := range mockChooseMap {
		keys = append(keys, k)
	}
	return strings.Join(keys, ",")
}

func (choose *ChooseCommand) exec(command string) string {
	fmt.Printf("exec command: %s\n", command)
	strarray := strings.Fields(strings.TrimSpace(command))
	return strarray[1]
}

func (selectCmd *SelectCommand) exec(command string) string {
	fmt.Printf("exec command: %s\n", command)
	strarray := strings.Fields(strings.TrimSpace(command))
	return fmt.Sprintf("%s %d", strarray[1], mockChooseMap[strarray[1]])
}

func (update *UpdateCommand) exec(command string) string {
	fmt.Printf("exec command: %s\n", command)
	strarray := strings.Fields(strings.TrimSpace(command))

	v, _ := strconv.ParseInt(strarray[1], 0, 64)
	mockChooseMap[strarray[2]] = int(v)

	return fmt.Sprintf("update %s successfully!", strarray[2])
}

func CommandInvoker(command string) string {
	commands := strings.Split(command, "|")

	prevExecResult := ""
	for _, v := range commands {
		currCmd := fmt.Sprintf("%s %s", strings.Trim(v, " "), prevExecResult)
		result := ""
		if strings.Contains(v, "ls") {
			cmd := &LsCommand{}
			result = cmd.exec(currCmd)
		} else if strings.Contains(v, "select") {
			cmd := &SelectCommand{}
			result = cmd.exec(currCmd)
		} else if strings.Contains(v, "choose") {
			cmd := &ChooseCommand{}
			result = cmd.exec(currCmd)
		} else if strings.Contains(v, "update") {
			cmd := &UpdateCommand{}
			result = cmd.exec(currCmd)
		}

		fmt.Println(result)
		prevExecResult = result
	}

	return prevExecResult
}

command_test.go

package designpattern_test

import (
	designpattern "ptarmigan-golang-design-pattern/src"
	"testing"
)

func TestCommand(t *testing.T) {

	oldValue := designpattern.CommandInvoker("select John")
	if oldValue != "John 7" {
		t.Error("old value of John dose not equals 7")
	}
	designpattern.CommandInvoker("ls | choose John | select | update 0")
	currValue := designpattern.CommandInvoker("select John")
	if currValue != "John 0" {
		t.Error("old value of John dose not equals 0")
	}
}


result:

exec command: select John 
John 7
exec command: ls 
Lisa,Nick,Martin,Benjamin,John
exec command: choose John Lisa,Nick,Martin,Benjamin,John
John
exec command: select John
John 7
exec command: update 0 John 7
update John successfully!
exec command: select John 
John 0
PASS