Golangで、デザインパターン「Command」を学ぶ

GoFのデザインパターンをGolangで学習してみたいと思います。
今回は、Qiita記事: "[Pythonで、デザインパターン「Command」を学ぶ](https://qiita.com/ttsubo/items/80fcaa529ce9f37e2543)"で取り上げた、Pythonベースの”Command”のサンプルアプリをGolangで実装し直してみました。

# ■ Command（コマンド・パターン）
Command パターン（英: command pattern）はオブジェクト指向プログラミングにおけるデザインパターンの一つで、動作を表現するオブジェクトを示す。Command オブジェクトは、動作とそれに伴うパラメータをカプセル化したものである。
例として、印刷を行うライブラリが PrintJob クラスを備えているとする。ライブラリのユーザーは新たに PrintJob オブジェクトを作成し、パラメータ（印刷するドキュメント、印刷部数など）をセットし、最後にプリンターにジョブを送信するメソッドを呼び出す。

## UML class and sequence diagram
![W3sDesign_Command_Design_Pattern_UML.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103595/4290554a-b93f-bf3f-efab-eeda08b45f59.jpeg)
## UML class diagram
![command.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103595/f3e8024e-2b00-9240-bac8-694521ad36e5.png)
[(以上、ウィキペディア（Wikipedia）より引用)](https://ja.wikipedia.org/wiki/Command_パターン)


# ■ "Command"のサンプルプログラム
実際に、Commandパターンを活用したサンプルプログラムを動かしてみて、次のような動作の様子を確認したいと思います。

- ファイル権限"777"の`test1.txt`ファイルを作成する
- ファイル権限"600"の`test2.txt`ファイルを作成する

なお、サンプルプログラムは、第一引数：作成したいファイル名、第二引数：付与したいファイル権限とします。

```console
$ go run Main.go test1.txt 777
% touch test1.txt
% chmod 777 test1.txt
```
```
$ go run Main.go test2.txt 600
% touch test2.txt
% chmod 600 test2.txt
```
ファイル一覧を確認します。

```console
$ ls -l|grep test
-rwxrwxrwx  1 ttsubo  staff    0  3 29 05:28 test1.txt
-rw-------  1 ttsubo  staff    0  3 29 05:29 test2.txt
```
想定どおり、ファイルが生成できました。

# ■ サンプルプログラムの詳細
Gitリポジトリにも、同様のコードをアップしています。
https://github.com/ttsubo/study_of_design_pattern_with_golang/tree/master/Command

- ディレクトリ構成

```console
.
├── Main.go
└── command
    └── command.go
```
## (1) Command（命令）の役
命令のインタフェースを定める役です。
サンプルプログラムでは、`command`インタフェースが、この役を努めます。

```go:command/command.go
package command

import (
	"fmt"
	"os"
)

type command interface {
	execute()
	display()
}
```
## (2) ConcreteCommand（具体的命令）の役
`Command`役のインタフェースを実際に実装している役です。
サンプルプログラムでは、`FileTouchCommand`構造体と `ChmodCommand`構造体が、この役を努めます。

```go:command/command.go
// FileTouchCommand is struct
type FileTouchCommand struct {
	filename string
	receiver *FileOperator
}

// NewFileTouchCommand func for initializing FileTouchCommand
func NewFileTouchCommand(filename string, receiverObj *FileOperator) *FileTouchCommand {
	return &FileTouchCommand{
		filename: filename,
		receiver: receiverObj,
	}
}

func (f *FileTouchCommand) execute() {
	f.receiver.createFile(f.filename)
}

func (f *FileTouchCommand) display() {
	fmt.Printf("%% touch %s\n", f.filename)
}
```
```go:command/command.go
// ChmodCommand is struct
type ChmodCommand struct {
	filename   string
	permission uint64
	receiver   *FileOperator
}

// NewChmodCommand func for initializing ChmodCommand
func NewChmodCommand(filename string, permission uint64, receiverObj *FileOperator) *ChmodCommand {
	return &ChmodCommand{
		filename:   filename,
		permission: permission,
		receiver:   receiverObj,
	}
}

func (c *ChmodCommand) execute() {
	c.receiver.changeFileMode(c.filename, c.permission)
}

func (c *ChmodCommand) display() {
	fmt.Printf("%% chmod %o %s\n", c.permission, c.filename)
}
```
## (3) Receiver（受信者）の役
`ConcreteCommand`役の命令を実行するときに対象となる役です。命令の受け取り手と呼んでもよいでしょう。
サンプルプログラムでは、`FileOperator`構造体が、この役を努めます。

```go:command/command.go
// FileOperator is struct
type FileOperator struct {
}

// NewFileOperator func for initializing FileOperator
func NewFileOperator() *FileOperator {
	return &FileOperator{}
}

func (f *FileOperator) createFile(filename string) {
	os.Create(filename)
}

func (f *FileOperator) changeFileMode(filename string, permission uint64) {
	os.Chmod(filename, os.FileMode(permission))
}
```

## (4) Invoker（起動者）の役
命令の実行を開始する役です。`Command`役で定義されているインタフェースを呼び出す役になります。
サンプルプログラムでは、`CompositeCommand`構造体が、この役を努めます。

```go:command/command.go
// CompositeCommand is struct
type CompositeCommand struct {
	cmds []command
}

//NewCompositeCommand func for initializing CompositeCommand
func NewCompositeCommand() *CompositeCommand {
	return &CompositeCommand{}
}

// AppendCmd func for appending command
func (c *CompositeCommand) AppendCmd(cmd command) {
	c.cmds = append(c.cmds, cmd)
}

// Execute func for executing command
func (c *CompositeCommand) Execute() {
	for _, cmd := range c.cmds {
		cmd.execute()
	}
}
```
## (5) Client（依頼人）の役
`ConcreteCommand`役を生成し、その際にReceiver役を割り当てる役です。
サンプルプログラムでは、`startMain`関数が、この役を努めます。

```go:Main.go
package main

import (
	"flag"
	"strconv"

	"./command"
)

func startMain(filename string, permission uint64) {
	recv := command.NewFileOperator()
	cc := command.NewCompositeCommand()
	cc.AppendCmd(command.NewFileTouchCommand(filename, recv))
	cc.AppendCmd(command.NewChmodCommand(filename, permission, recv))
	cc.Execute()
	cc.Display()
}

func main() {
	flag.Parse()
	perm32, _ := strconv.ParseUint(flag.Arg(1), 8, 32)
	startMain(flag.Arg(0), perm32)
}
```

# ■ 参考URL
- [Pythonで、デザインパターン「Command」を学ぶ](https://qiita.com/ttsubo/items/80fcaa529ce9f37e2543)