Command Pattern (디자인 패턴 6장)

커맨드 패턴 정의

커맨드 패턴을 이용하면 요구 사항을 객체로 캡슐화 할 수 있으며, 매개변수를 써서 여러 가지 다른 요구 사항을 집어넣을 수도 있습니다.
또한 요청 내역을 큐에 저장하거나 로그로 기록할 수도 있으며, 작업취소 기능도 지원 가능합니다.

아래의 코드를 보자.

class CommandPatternTest {

    class RemoteControl {
        private val onCommand: HashMap<Int, Command> = hashMapOf()
        private val offCommand: HashMap<Int, Command> = hashMapOf()
        private var unDoCommand: Command? = null

        fun addCommand(slot: Int, onCommand: Command, offCommand: Command) {
            this.onCommand[slot] = onCommand
            this.offCommand[slot] = offCommand
        }

        fun onButtonWasPushed(slot: Int) {
            onCommand[slot]?.let {
                it.execute()
                unDoCommand = it
            }
        }

        fun offButtonWasPushed(slot: Int) {
            offCommand[slot]?.let {
                it.execute()
                unDoCommand = it
            }
        }

        fun unDoButtonWasPushed() {
            unDoCommand?.let {
                it.undo()
            }
        }
    }

    interface Command {
        fun execute()
        fun undo()
    }

    class Light {
        fun on() {
            println("Light On")
        }

        fun off() {
            println("Light Off")
        }
    }

    class LightOffCommand(private val light: Light) : Command {
        override fun execute() {
            light.off()
        }

        override fun undo() {
            light.on()
        }
    }

    class LightOnCommand(private val light: Light) : Command {
        override fun execute() {
            light.on()
        }

        override fun undo() {
            light.off()
        }
    }

    class KitchenLight {
        fun on() {
            println("KitchenLight On")
        }

        fun off() {
            println("KitchenLight Off")
        }
    }

    class KitchenOffCommand(private val kitchenLight: KitchenLight) : Command {
        override fun execute() {
            kitchenLight.off()
        }

        override fun undo() {
            kitchenLight.on()
        }
    }

    class KitchenOnCommand(private val kitchenLight: KitchenLight) : Command {
        override fun execute() {
            kitchenLight.on()
        }

        override fun undo() {
            kitchenLight.off()
        }
    }

    @Test
    fun testRemoteControl() {
        val remoteControl = RemoteControl()
        val light = Light()
        remoteControl.addCommand(
            slot = 0,
            onCommand = LightOnCommand(
                light
            ),
            offCommand = LightOffCommand(
                light
            )
        )

        val kitchenLight = KitchenLight()
        remoteControl.addCommand(
            slot = 1,
            onCommand = KitchenOnCommand(
                kitchenLight
            ),
            offCommand = KitchenOffCommand(
                kitchenLight
            )
        )

        remoteControl.onButtonWasPushed(0)
        remoteControl.offButtonWasPushed(0)
        remoteControl.onButtonWasPushed(1)
        remoteControl.offButtonWasPushed(1)
        remoteControl.unDoButtonWasPushed()
    }

}

리모트컨트롤에서 Command 를 추가 해서 on,off 버튼을 사용할 수 있고 unDoCommand 를 통해 마지막 실행한 명령을 되돌릴 수 있다. 아래는 테스트 결과 이미지이다.