겨울 세일!
커맨드

자바로 작성된 커맨드

커맨드는 요청 또는 간단한 작업을 객체로 변환하는 행동 디자인 패턴입니다.

이러한 변환은 명령의 지연 또는 원격 실행, 명령 기록 저장 등을 허용합니다.

복잡도:

인기도:

사용 예시들: 커맨드 패턴은 자바 코드에서 매우 일반적입니다. 대부분의 경우 작업으로 UI 요소를 매개 변수화하기 위한 콜백의 대안으로 사용되며 작업 대기, 작업 기록 추적 등에도 사용됩니다.

다음은 코어 자바 라이브러리로부터 가져온 몇 가지 예시들입니다:

식별: 특정 작업​(예: '복사', '잘라내기', '보내기', '인쇄' 등)​을 나타내는 관련 클래스들의 집합이 존재하는 경우 이는 커맨드 패턴일 수 있습니다. 이러한 클래스들은 같은 인터페이스/추상 클래스를 구현해야 합니다. 커맨드는 자체적으로 관련 작업을 구현하거나 작업을 별도의 객체​(수신자가 될 객체)​에 위임할 수 있습니다. 퍼즐의 마지막 조각은 호출자를 식별하는 것입니다. 자신의 메서드들 또는 생성자들의 매개변수들에서부터 커맨드 객체들을 받는 클래스를 검색하세요.

텍스트 편집기 커맨드들 및 실행 취소

이 예시의 텍스트 편집기는 사용자가 상호 작용할 때마다 새 커맨드 객체를 만듭니다. 작업을 실행한 후 명령이 기록 스택으로 푸시됩니다.

이제 실행 취소 작업을 수행하기 위해 응용 앱은 기록에서 마지막으로 실행된 명령을 가져와 역동작을 수행하거나 해당 명령에 따라 저장된 편집기의 과거 상태를 복원합니다.

commands

commands/Command.java: 추상 기초 커맨드

package refactoring_guru.command.example.commands;

import refactoring_guru.command.example.editor.Editor;

public abstract class Command {
    public Editor editor;
    private String backup;

    Command(Editor editor) {
        this.editor = editor;
    }

    void backup() {
        backup = editor.textField.getText();
    }

    public void undo() {
        editor.textField.setText(backup);
    }

    public abstract boolean execute();
}

commands/CopyCommand.java: 선택한 텍스트를 클립보드에 복사

package refactoring_guru.command.example.commands;

import refactoring_guru.command.example.editor.Editor;

public class CopyCommand extends Command {

    public CopyCommand(Editor editor) {
        super(editor);
    }

    @Override
    public boolean execute() {
        editor.clipboard = editor.textField.getSelectedText();
        return false;
    }
}

commands/PasteCommand.java: 클립보드에서 텍스트 붙여넣기

package refactoring_guru.command.example.commands;

import refactoring_guru.command.example.editor.Editor;

public class PasteCommand extends Command {

    public PasteCommand(Editor editor) {
        super(editor);
    }

    @Override
    public boolean execute() {
        if (editor.clipboard == null || editor.clipboard.isEmpty()) return false;

        backup();
        editor.textField.insert(editor.clipboard, editor.textField.getCaretPosition());
        return true;
    }
}

commands/CutCommand.java: 텍스트를 클립보드로 잘라내기

package refactoring_guru.command.example.commands;

import refactoring_guru.command.example.editor.Editor;

public class CutCommand extends Command {

    public CutCommand(Editor editor) {
        super(editor);
    }

    @Override
    public boolean execute() {
        if (editor.textField.getSelectedText().isEmpty()) return false;

        backup();
        String source = editor.textField.getText();
        editor.clipboard = editor.textField.getSelectedText();
        editor.textField.setText(cutString(source));
        return true;
    }

    private String cutString(String source) {
        String start = source.substring(0, editor.textField.getSelectionStart());
        String end = source.substring(editor.textField.getSelectionEnd());
        return start + end;
    }
}

commands/CommandHistory.java: 커맨드 기록

package refactoring_guru.command.example.commands;

import java.util.Stack;

public class CommandHistory {
    private Stack<Command> history = new Stack<>();

    public void push(Command c) {
        history.push(c);
    }

    public Command pop() {
        return history.pop();
    }

    public boolean isEmpty() { return history.isEmpty(); }
}

editor

editor/Editor.java: 그래픽 사용자 인터페이스 텍스트 편집기

package refactoring_guru.command.example.editor;

import refactoring_guru.command.example.commands.*;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Editor {
    public JTextArea textField;
    public String clipboard;
    private CommandHistory history = new CommandHistory();

    public void init() {
        JFrame frame = new JFrame("Text editor (type & use buttons, Luke!)");
        JPanel content = new JPanel();
        frame.setContentPane(content);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS));
        textField = new JTextArea();
        textField.setLineWrap(true);
        content.add(textField);
        JPanel buttons = new JPanel(new FlowLayout(FlowLayout.CENTER));
        JButton ctrlC = new JButton("Ctrl+C");
        JButton ctrlX = new JButton("Ctrl+X");
        JButton ctrlV = new JButton("Ctrl+V");
        JButton ctrlZ = new JButton("Ctrl+Z");
        Editor editor = this;
        ctrlC.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                executeCommand(new CopyCommand(editor));
            }
        });
        ctrlX.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                executeCommand(new CutCommand(editor));
            }
        });
        ctrlV.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                executeCommand(new PasteCommand(editor));
            }
        });
        ctrlZ.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                undo();
            }
        });
        buttons.add(ctrlC);
        buttons.add(ctrlX);
        buttons.add(ctrlV);
        buttons.add(ctrlZ);
        content.add(buttons);
        frame.setSize(450, 200);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private void executeCommand(Command command) {
        if (command.execute()) {
            history.push(command);
        }
    }

    private void undo() {
        if (history.isEmpty()) return;

        Command command = history.pop();
        if (command != null) {
            command.undo();
        }
    }
}

Demo.java: 클라이언트 코드

package refactoring_guru.command.example;

import refactoring_guru.command.example.editor.Editor;

public class Demo {
    public static void main(String[] args) {
        Editor editor = new Editor();
        editor.init();
    }
}

OutputDemo.png: 실행 결과

다른 언어로 작성된 커맨드

C#으로 작성된 커맨드 C++로 작성된 커맨드 Go로 작성된 커맨드 PHP로 작성된 커맨드 파이썬으로 작성된 커맨드 루비로 작성된 커맨드 러스트로 작성된 커맨드 스위프트로 작성된 커맨드 타입스크립트로 작성된 커맨드