디자인패턴

Command Pattern

hik14 2022. 8. 17. 10:30

정의

요청 내역을 객체로 캡슐화해서 객체를 서로 다른 요청 내역에 따라 매개변수화할 수 있습니다. 

요청을 큐에 저장하거나 로그로 기록하거나 작업 취소 기능을 사용할 수 있습니다.

 

커맨드 객체는 일련의 행동을 특정 리시버(실제 행위를 처리 하는 객체)와 연결하고 요청을 캡슐화한 것이다.

행동과 리시버를 한 객체에 넣고 execute() 메소드 하나만 외부에 공개하는 방법을 사용한다. 

 

*Invoker - command가 들어있으며, 특정 작업에 대한 수행을 요청한다. 

 

Comand 인터페이스 

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

Receiver 인터페이스 및 객체

interface TV{
    fun on()

    fun off()

    fun setVolume()

    fun setInputChannel()
}

class LgTv: TV{
    override fun on() {
        println("LgTv가 켜졌습니다.")
    }

    override fun off() {
        println("LgTv가 꺼졌습니다.")
    }

    override fun setVolume() {
        println("음량 조절")
    }

    override fun setInputChannel() {
        println("채널 변경")
    }

}

interface AirConditioner{
    fun on()

    fun off()

    fun setDirection()

    fun setAirVolume()
}

class SAMSUNGAirConditioner: AirConditioner{
    override fun on() {
       println("삼성에어컨이 켜졌습니다")
    }

    override fun off() {
        println("삼성에어컨이 꺼습니다")
    }

    override fun setDirection() {
        println("풍향 조절")
    }

    override fun setAirVolume() {
        println("풍량 조절")
    }
}

interface Light{
    fun on()

    fun off()

    fun brightnessAdjustment()
}

class LivingRoomLight: Light{
    override fun on() {
        println("거실등이 켜졌습니다.")
    }

    override fun off() {
        println("거실등이 꺼졌습니다.")
    }

    override fun brightnessAdjustment() {
        println("거실등 밝기 조절")
    }
}

On Command

class TvOnCommander(private val tv: TV): Command{
    override fun execute() {
        tv.on()
    }

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


class AirConditionerOnCommander(private val airConditioner: AirConditioner): Command{
    override fun execute() {
        airConditioner.on()
    }

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


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

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

Off Command

class TvOffCommander(private val tv: TV): Command{
    override fun execute() {
        tv.off()
    }

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


class AirConditionerOffCommander(private val airConditioner: AirConditioner): Command{
    override fun execute() {
        airConditioner.off()
    }

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


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

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

Invoker(RemoteControl)

class RemoteControl{

    private val onCommandList = arrayOfNulls<Command>(3)
    private val offCommandList = arrayOfNulls<Command>(3)

    private var unDoCommand: Command? = null

    fun setCommand(slotNum: Int, onCommand: Command, offCommand: Command){
        onCommandList[slotNum-1] = onCommand
        offCommandList[slotNum-1] = offCommand
    }

    fun on(slotNum: Int){
        onCommandList[slotNum-1]?.execute()
        unDoCommand = offCommandList[slotNum-1]
    }

    fun off(slotNum: Int){
        offCommandList[slotNum-1]?.execute()
        unDoCommand = offCommandList[slotNum-1]
    }

    fun cancel(){
        println("--cancel--")
        unDoCommand?.undo()
    }
}

실행결과 

fun main() {
    val remoteControl = RemoteControl()

    val tvOnCommander = TvOnCommander(LgTv())
    val tvOffCommander = TvOffCommander(LgTv())

    remoteControl.setCommand(1, tvOnCommander, tvOffCommander)
    remoteControl.on(1)
    remoteControl.cancel()

    remoteControl.off(1)
    remoteControl.cancel()
}