
💡 NOTE
커맨드 패턴을 이용하면 요구사항을 객체로 캡슐화 할 수 있으며, 매개변수를 써서 여러 가지 다른 요구사항을 집어넣을 수도 있습니다. 또한 요청 내역을 큐에 저장하거나 로그로 기록할 수도 있으며, 작업 취소 기능도 지원 가능합니다.
1.Command 인터페이스 만들기
protocol Command {
    func execute()
}2.전등을 켜기 위한 커맨드 클래스 구현
public class Light {
    public func on() { print("Light On") }
    public func off() { print("Light Off") }
}
//1
public class LightOnCommand: Command {
		//2
    let light: Light
    init(light: Light) {
        self.light = light
    }
		//3
    public func execute() {
        light.on()
    }
}주석 1 : 우리가 만들어야 할 리모컨은 전등을 On 할수 있어야 하므로, 클라이언트가 리모컨을 눌렀을때 전등을 on하라는 명령을 내릴 Command 인터페이스를 구현하는 LightOnCommand를 생성해주어야 합니다.주석 2 : 앞서 커맨드는 리시버(전등)을 알아야 된다고 했으므로, LightOnCommand에서는 전등을 가지고 있어야 합니다.주석 3: LightOnCommand는 구체 클래스이므로 execute()에서 전등을 on 하라는 명령을 수행합니다.3.커맨드 객체 사용하기
public class SimpleRemoteControl {
		//1
    var slot: Command?
    //2
    func setCommand(command: Command) {
        slot = command
    }
    //3
    func buttonWasPressed() {
        slot?.execute()
    }
}주석 1 : 인보커인 리모컨은 커맨드를 통해 리시버와 통신하기 때문에 커맨드 인스턴스 변수를 가지고 있어야 합니다. 다만, 구체 커맨드 클래스를 가지는 것이 아니라 Command 인터페이스를 의존하고 사용하여 의존성 역전이 이루어진 구조이어야 합니다.주석 2 : 외부에서 구체 커맨드 클래스를 주입해주기 위한 메소드가 필요합니다. 이를 통해 인보커는 단순히 무언가를 execute() 하는 역할만 하고, 자신이 구체적으로 어떤 작업을 하는지에 대해 전혀 신경쓰지 않을 수 있습니다.주석 3 : 실행 명령을 내립니다.4.리코먼을 사용해봅시다
let remote = SimpleRemoteControl()
let light = Light()
let lightOn = LightOnCommand(light: light)
remote.setCommand(command: lightOn)
remote.buttonWasPressed()
---result---
Light Onremote 상수가 되겠습니다.lightOn 상수가 되겠습니다.light 상수가 되겠습니다.remote.setCommand()를 통해 command 구체 클래스를 주입해줍니다.remote는 이제 lightOn이라는 구체 커맨드 클래스에서 구현하고 있는 execute()를 통해 전등을 on 시킬 수 있습니다.