디자인 패턴

Command Pattern

kyoulho 2024. 4. 28. 18:03

커맨드 패턴은 명령을 객체로 캡슐화하여 관리할 수 있게 한다.

 

커맨드 패턴이 사용되는 상황

  1. 요청과 수신자의 분리: 커맨드 패턴을 사용하면 요청을 하는 객체(클라이언트)와 실제 작업을 수행하는 객체(수신자)를 분리할 수 있다.
  2. 연산의 매개변수화: 커맨드 객체를 사용하면 다양한 연산을 하나의 인터페이스를 통해 호출할 수 있다. 각 커맨드는 특정 연산을 수행하며, 이를 인터페이스로 추상화함으로써 클라이언트는 어떤 작업을 수행할지 결정할 수 있다.
  3. 작업 취소 및 다시 실행(Undo/Redo): 커맨드 패턴을 사용하면 수행된 명령을 저장하고, 나중에 이 명령을 다시 실행하거나 취소할 수 있는 기능을 구현하기에 용이하다. 이는 Undo 및 Redo 기능을 지원하는 애플리케이션에서 유용하다.
  4. 큐 형태의 명령 처리: 명령을 큐에 저장하고 순서대로 실행할 수 있다. 이를 통해 명령의 처리 순서를 관리하거나, 작업을 비동기적으로 수행할 수 있다.

구성 요소

  1. Command (명령):명령 인터페이스를 정의하며, execute 메서드를 선언한다.
  2. ConcreteCommand (구체적인 명령): Command 인터페이스를 구현하는 실제 명령 클래스. 수신자(Receiver) 객체에 대한 호출을 캡슐화한다.
  3. Client (클라이언트): 명령 객체를 생성하고, 필요한 커맨드를 설정한다.
  4. Invoker (호출자): 명령 객체를 저장하고, 명령의 실행을 요청하는 역할을 한다.
  5. Receiver (수신자): 명령에 의해 수행되어야 할 실제 작업을 담당하는 객체.

예제

import java.util.Stack;

// Command interface
interface Command {
    void execute();
}

// Receiver
class TextEditor {
    private StringBuilder text = new StringBuilder();
    private Stack<String> history = new Stack<>();

    void addText(String newText) {
        history.push(text.toString());
        text.append(newText);
        System.out.println("텍스트 추가: " + newText);
    }

    void undo() {
        if (!history.isEmpty()) {
            text = new StringBuilder(history.pop());
            System.out.println("Undo: " + text);
        } else {
            System.out.println("더 이상 Undo할 내역이 없습니다.");
        }
    }

    void redo() {
        if (!history.isEmpty()) {
            String redoText = history.pop();
            text = new StringBuilder(redoText);
            history.push(redoText);
            System.out.println("Redo: " + redoText);
        } else {
            System.out.println("더 이상 Redo할 내역이 없습니다.");
        }
    }

    @Override
    public String toString() {
        return "TextEditor{" +
                "text='" + text + '\'' +
                '}';
    }
}

// Concrete Command to add text
class AddTextCommand implements Command {
    private TextEditor textEditor;
    private String text;

    AddTextCommand(TextEditor textEditor, String text) {
        this.textEditor = textEditor;
        this.text = text;
    }

    @Override
    public void execute() {
        textEditor.addText(text);
    }
}

// Invoker
class TextEditorApp {
    private Command command;

    void setCommand(Command command) {
        this.command = command;
    }

    void executeCommand() {
        command.execute();
    }
}

// Main class
public class Main {
    public static void main(String[] args) {
        // Receiver
        TextEditor textEditor = new TextEditor();

        // Concrete Commands
        Command addText1Command = new AddTextCommand(textEditor, "Hello ");
        Command addText2Command = new AddTextCommand(textEditor, "world!");

        // Invoker
        TextEditorApp textEditorApp = new TextEditorApp();

        // Add text
        textEditorApp.setCommand(addText1Command);
        textEditorApp.executeCommand(); // 텍스트 추가: Hello 

        textEditorApp.setCommand(addText2Command);
        textEditorApp.executeCommand(); // 텍스트 추가: world!

        // Undo
        textEditor.undo(); // Undo: Hello 

        // Redo
        textEditor.redo(); // Redo: Hello world!
    }
}

'디자인 패턴' 카테고리의 다른 글

Decorator Pattern  (0) 2024.05.05
Composite Pattern  (1) 2024.05.01
Chain Of Responsibility Pattern  (0) 2024.04.27
Bridge Pattern  (0) 2024.04.10
Adapter Pattern  (0) 2024.04.10