
Command を Go で
Command は、 振る舞いに関するデザインパターンの一つで、 リクエストや簡単な操作をオブジェクトに変換します。
変換により、 コマンドの遅延実行や遠隔実行を可能にしたり、 コマンドの履歴の保存を可能にしたりできます。
概念的な例
Command パターンを、 テレビを例にとってみてみましょう。 テレビの電源を入れるには、 以下のどちらかを押します:
- リモコンのオンのボタン
- 実際のテレビのオンのボタン
「オンにする」 コマンド・オブジェクトの実装は、 テレビを受け手として開始します。 このコマンドの実行メソッドが呼ばれると、 それは次に TV.on
関数を呼び出します。 次に、 インボーカーを定義します。 実際のところ、 インボーカーは二つあります。 リモコンとテレビ自身です。 両方とも 「オンにする」 コマンド・オブジェクトを埋め込んでいます。
同じリクエストを複数のインボーカーでラップしていることに注目してください。 他のコマンドでも同様です。 別々のコマンド・オブジェクトを作成する利点は、 UI ロジックをビジネス・ロジックから切り離すことです。 インボーカーごとに異なるハンドラーを開発する必要はありません。 コマンド・オブジェクトには、 実行に必要なすべての情報が含まれています。 そのため、 遅延実行にも使用できます。
button.go: インボーカー
package main
type Button struct {
command Command
}
func (b *Button) press() {
b.command.execute()
}
command.go: コマンド・インターフェース
package main
type Command interface {
execute()
}
onCommand.go: 具象コマンド
package main
type OnCommand struct {
device Device
}
func (c *OnCommand) execute() {
c.device.on()
}
offCommand.go: 具象コマンド
package main
type OffCommand struct {
device Device
}
func (c *OffCommand) execute() {
c.device.off()
}
device.go: 受け手インターフェース
package main
type Device interface {
on()
off()
}
tv.go: 具象受け手
package main
import "fmt"
type Tv struct {
isRunning bool
}
func (t *Tv) on() {
t.isRunning = true
fmt.Println("Turning tv on")
}
func (t *Tv) off() {
t.isRunning = false
fmt.Println("Turning tv off")
}
main.go: クライアント・コード
package main
func main() {
tv := &Tv{}
onCommand := &OnCommand{
device: tv,
}
offCommand := &OffCommand{
device: tv,
}
onButton := &Button{
command: onCommand,
}
onButton.press()
offButton := &Button{
command: offCommand,
}
offButton.press()
}
output.txt: 実行結果
Turning tv on
Turning tv off