Command

デザインパターンとは

デザインパターンとはオブジェクト思考開発における先人たちが作り上げてきた便利な設計図です。

Gang of Four通称Gofが1994年に出版した『オブジェクト指向における再利用のためのデザインパターン』の中で23個の設計図が紹介されています。

Note

デザインパターンのサンプルコードはSwift4でまとめます。

コマンドパターンとは?

コマンドパターンは命令を1つのオブジェクトとして作成します。

あるオブジェクトに対してコマンドを送ることでそのオブジェクトのメソッドを呼び出します。

既存のコードを修正することなく拡張することができることと、クラスの再利用性が向上することがコマンドパターンの強みです。

 サンプルコード

サンプルコードでは料理をする際の調理過程をコマンドオブジェクトとして作成しています。

Commandプロトコル

レシーバーをメンバとして保持させるようにしていますがこれはレシーバーが複数作ることが可能ということになります。

protocol Command {
    var receiver: Receiver { get }
    init(receiver: Receiver)
    func execute()
}

Command

料理のコマンドとして切る、煮る、炒めるの3つを作成しています。レシーバーを通して処理を実行しています

class Cut: Command {
    var receiver: Receiver
    
    required init(receiver: Receiver) {
       self.receiver = receiver
    }
    func execute() {
        receiver.action(toDo: "切る!")
    }
}

class Simmer: Command {
    var receiver: Receiver
    
    required init(receiver: Receiver) {
        self.receiver = receiver
    }
    func execute() {
        receiver.action(toDo: "煮る!!")
    }
}

class StirFly: Command {
    var receiver: Receiver
    
    required init(receiver: Receiver) {
        self.receiver = receiver
    }
    func execute() {
        receiver.action(toDo: "炒める!!!")
    }
}

Receiver

ReceiverはCommandのメソッドの処理を受け取っています。料理レシーバーしか作っていませんが、他のレシーバーを増やすことも可能です。

protocol Receiver {
    func action(toDo: String)
}

class Cooking: Receiver {
    func action(toDo: String) {
        print(toDo)
    }
}

Invoker

Invokerはコマンドをためておくクラスです。cookingStartメソッドを呼び出せば貯めておいた任意の順番で料理のコマンドを実行することができます。


class Invoker {
    var commands: [Command] = [Command]()
    
    func addCommand(command: Command) {
        self.commands.append(command)
    }
    func cookingStart() {
        for command in commands {
            command.execute()
        }
    }
}

呼び出し元

let cook = Invoker()
let cooking = Cooking()

let cut = Cut(receiver: cooking)
let simmer = Simmer(receiver: cooking)
let stirFly = StirFly(receiver: cooking)

cook.addCommand(command: cut)
cook.addCommand(command: stirFly)
cook.addCommand(command: simmer)

cook.cookingStart()

コンソール

切る!
炒める!!!
煮る!!

コード一覧

import UIKit

protocol Command {
    var receiver: Receiver { get }
    init(receiver: Receiver)
    func execute()

}
class Cut: Command {
    var receiver: Receiver
    
    required init(receiver: Receiver) {
       self.receiver = receiver
    }
    func execute() {
        print("切る!")
    }
}

class Simmer: Command {
    var receiver: Receiver
    
    required init(receiver: Receiver) {
        self.receiver = receiver
    }
    func execute() {
        print("煮る!!")
    }
}

class StirFly: Command {
    var receiver: Receiver
    
    required init(receiver: Receiver) {
        self.receiver = receiver
    }
    func execute() {
        print("炒める!!!")
    }
}

protocol Receiver {
    func action(toDo: String)
}

class Cooking: Receiver {
    func action(toDo: String) {
        print(toDo)
    }
}

class Invoker {
    var commands: [Command] = [Command]()
    
    func addCommand(command: Command) {
        self.commands.append(command)
    }
    func cookingStart() {
        for command in commands {
            command.execute()
        }
    }
    
}

let cook = Invoker()
let cooking = Cooking()

let cut = Cut(receiver: cooking)
let simmer = Simmer(receiver: cooking)
let stirFly = StirFly(receiver: cooking)

cook.addCommand(command: cut)
cook.addCommand(command: simmer)
cook.addCommand(command: stirFly)

cook.cookingStart()

参考文献

Swiftで学ぶデザインパターン22 (Commandパターン)

Commandパターンについて調べた

命令をクラスにするCommandパターン

Commandパターン