ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Command Pattern(커맨드 패턴)
    STUDY/디자인패턴 2025. 1. 21. 18:59

    커맨드 패턴이란?

    요청을 요청에 대한 모든 정보가 포함된 독립실행형 객체로 변환하는 행동 디자인 패턴으로, 이 변환은 다양한 요청들이 있는 메서드들을 인수화할 수 있도록 하며, 요청의 실행을 지연 또는 대기열에 넣을 수 있도록 하고, 또 실행 취소할 수 있는 작업을 지원할 수 있도록 한다.

     

    즉, 요청을 객체의 형태로 캡슐화하여 사용자가 보낸 요청을 나중에 이용할 수 있도록 메서드 이름, 매개변수 등 요청에 필요한 정보를 저장 또는 로깅, 취소할 수 있게 하는 패턴이다.

     

    구조

    Invoker(발동자)

    요청들을 시작하는 역할을 한다. 커맨드 객체에 대한 참조 필드를 가지고 있고, 요청을 수신자에게 직접 보내는 대신 해당 커맨드를 작동시킨다. 일반적으로 커맨드 객체를 생성하지 않고 클라이언트로부터 이미 생성된 커맨드를 받는다.

     

    Command(명령)

    커맨드를 실행하기 위한 단일 메서드만을 선언하는 인터페이스

     

    Concrete Command

    다양한 유형의 요청을 구현한다. 자체적으로 작업을 수행해서는 안되며, 비즈니스 논리 객체 중 하나에 호출을 전달해야 한다. 수신 객체에서 메서드를 실행하는 데 필요한 매개변수들을 필드로 선언해 가지고 있을 수 있고, 생성자를 통해서만 필드를 초기화하여 불변 객체로 만들 수 있다.

     

    Receiver(수신자)

    비즈니스 로직이 포함된 클래스로, 명령 실행에 필요한 실제 작업을 수행한다.

     

    Client

    커맨드 객체를 생성하고, 수신자 인스턴스를 포함한 모든 요청 매개변수들을 커맨드의 생성자로 전달한다.

     

    예시

     

    Command

    public interface Command {
        void execute();
    }

     

    ConcreteCommand

    public class CopyCommand implements Command {
        private Editor editor;
        private String selection;
    
        public CopyCommand(Editor editor, String selection) {
            this.editor = editor;
            this.selection = selection;
        }
    
        @Override
        public void execute() {
            editor.copy(selection);
        }
    }
    
    public class PasteCommand implements Command {
        private Editor editor;
    
        public PasteCommand(Editor editor) {
            this.editor = editor;
        }
    
        @Override
        public void execute() {
            editor.paste();
        }
    }

     

    Receiver

    public class Editor {
        private String clipboard = "";
        private String text = "";
    
        public void copy(String text) {
            clipboard = text;
            System.out.println("Copied to clipboard: " + clipboard);
        }
    
        public void paste() {
            text += clipboard;
            System.out.println("Text after paste: " + text);
        }
    
        public String getText() {
            return text;
        }
    
        public void setText(String text) {
            this.text = text;
        }
    }

     

    Invoker

    public class CommandInvoker {
        private Command command;
    
        public void setCommand(Command command) {
            this.command = command;
        }
    
        public void executeCommand() {
            if (command != null) {
                command.execute();
            } else {
                System.out.println("No command to execute.");
            }
        }
    }

     

    Client

    public class Client {
        public static void main(String[] args) {
            // Receiver
            Editor editor = new Editor();
    
            // Commands
            Command copyCommand = new CopyCommand(editor, "Hello, world!");
            Command pasteCommand = new PasteCommand(editor);
    
            // Invoker
            CommandInvoker invoker = new CommandInvoker();
    
            // Execute copy command
            invoker.setCommand(copyCommand);
            invoker.executeCommand();
    
            // Execute paste command
            invoker.setCommand(pasteCommand);
            invoker.executeCommand();
        }
    }

     

    적용

    1. 객체를 매개변수화하려는 경우
    2. 작업들의 실행을 예약하거나, 작업들을 큐에 넣거나 원격으로 실행하려는 경우
    3. 되돌릴 수 있는 작업을 구현하려는 경우

     

    장단점

    장점

    • 단일 책임 원칙, 작업을 호출하는 클래스들을 이러한 작업을 수행하는 클래스들로부터 분리할 수 있다.
    • 개방/폐쇄 원칙, 기존 클라이언트 코드를 수정하지 않고 새 커맨드를 추가할 수 있다.
    • 실행 취소/다시 실행을 구현할 수 있다.
    • 작업들의 지연된 실행을 구현할 수 있다.
    • 간단한 커맨드들의 집합을 복잡한 커맨드로 조합할 수 있다.

     

    단점

    • 발송자와 수신자 사이에 완전히 새로운 레이어를 도입하기 때문에 코드가 더 복잡해질 수 있다.

     

Designed by Tistory.