PHpullh
학습 라이브러리/Kotlin/커맨드 패턴 (Command)

KOTLIN · 디자인패턴

커맨드 패턴 (Command)

요청을 객체로 캡슐화하여 실행, 취소, 큐잉을 지원합니다. 편집기의 Undo/Redo에 적합합니다.

디자인패턴중급commandundo-redohistoryencapsulation

핵심 설명

요청을 객체로 캡슐화하여 실행, 취소, 큐잉을 지원합니다. 편집기의 Undo/Redo에 적합합니다.

Kotlin code

interface Command {
    fun execute()
    fun undo()
    val description: String
}

class TextEditor {
    var content = ""
        private set

    fun insert(text: String) { content += text }
    fun deleteLast(count: Int) {
        content = content.dropLast(count)
    }
    override fun toString() = "[$content]"
}

class InsertCommand(private val editor: TextEditor, private val text: String) : Command {
    override val description = "삽입: '$text'"
    override fun execute() = editor.insert(text)
    override fun undo() = editor.deleteLast(text.length)
}

class CommandHistory {
    private val undoStack = ArrayDeque<Command>()
    private val redoStack = ArrayDeque<Command>()

    fun execute(cmd: Command) {
        cmd.execute()
        undoStack.addLast(cmd)
        redoStack.clear()
        println("실행: ${cmd.description} → $cmd")
    }
    fun undo() {
        undoStack.removeLastOrNull()?.let {
            it.undo(); redoStack.addLast(it)
            println("취소: ${it.description}")
        }
    }
    fun redo() {
        redoStack.removeLastOrNull()?.let {
            it.execute(); undoStack.addLast(it)
            println("재실행: ${it.description}")
        }
    }
}

fun main() {
    val editor = TextEditor()
    val history = CommandHistory()
    history.execute(InsertCommand(editor, "Hello"))
    history.execute(InsertCommand(editor, " World"))
    println("현재: $editor")
    history.undo()
    println("undo: $editor")
    history.redo()
    println("redo: $editor")
}

학습 팁

커맨드 패턴은 매크로(여러 커맨드 묶음), 트랜잭션(모두 성공 또는 모두 롤백), 로깅에도 활용됩니다.

주의할 점

undo 구현이 불완전하면 상태가 일치하지 않습니다. 각 커맨드의 undoexecute의 역연산인지 반드시 검증하세요.

자주 묻는 질문

커맨드 패턴 (Command)란 무엇인가요?

요청을 객체로 캡슐화하여 실행, 취소, 큐잉을 지원합니다. 편집기의 Undo/Redo에 적합합니다.

커맨드 패턴 (Command) 학습 시 주의할 점은 무엇인가요?

undo 구현이 불완전하면 상태가 일치하지 않습니다. 각 커맨드의 undo 가 execute 의 역연산인지 반드시 검증하세요.