Menu
Coddy logo textTech

커맨드 패턴

Coddy Dart 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 110개 중 94번째.

커맨드 패턴(Command pattern)은 요청을 객체로 캡슐화하여, 클라이언트를 서로 다른 요청으로 매개변수화하거나, 작업을 큐에 저장하거나, 실행 취소 기능을 지원할 수 있게 합니다. 메서드를 직접 호출하는 대신, 액션을 저장, 전달 또는 나중에 실행할 수 있는 커맨드 객체 안에 감쌉니다.

이 패턴은 세 가지 핵심 구성 요소로 이루어집니다: execute 메서드를 가진 Command 인터페이스, 특정 작업을 구현하는 Concrete Commands, 그리고 실제 작업을 수행하는 Receiver입니다. 선택 사항인 Invoker는 명령이 무엇을 하는지 알지 못한 채 명령을 트리거합니다:

abstract class Command {
  void execute();
}

class Light {
  void turnOn() => print('Light is ON');
  void turnOff() => print('Light is OFF');
}

class TurnOnCommand implements Command {
  final Light light;
  TurnOnCommand(this.light);

  @override
  void execute() => light.turnOn();
}

class TurnOffCommand implements Command {
  final Light light;
  TurnOffCommand(this.light);

  @override
  void execute() => light.turnOff();
}

class RemoteControl {
  Command? _command;

  void setCommand(Command command) {
    _command = command;
  }

  void pressButton() {
    _command?.execute();
  }
}

void main() {
  var light = Light();
  var remote = RemoteControl();

  remote.setCommand(TurnOnCommand(light));
  remote.pressButton();  // Light is ON

  remote.setCommand(TurnOffCommand(light));
  remote.pressButton();  // Light is OFF
}

RemoteControl은 조명에 대해 아무것도 알지 못합니다. 그저 주어진 명령이 무엇이든 실행할 뿐입니다. 이러한 디커플링(decoupling) 덕분에 인보커(invoker)를 수정하지 않고도 새로운 명령을 쉽게 추가할 수 있습니다. 커맨드 패턴은 작업을 일급 객체로 취급해야 하는 실행 취소/다시 실행 시스템, 작업 큐 또는 매크로 기록을 구현하는 데 이상적입니다.

challenge icon

챌린지

쉬움

Command 패턴을 사용하여 텍스트 에디터 명령 시스템을 만들어 봅시다! 텍스트 작업을 명령 객체로 캡슐화하는 시스템을 만들게 됩니다. 이를 통해 에디터는 각 작업의 세부 사항을 알지 못해도 다양한 동작을 실행할 수 있습니다. 이것은 Command 패턴의 전형적인 사용 사례입니다. 각 동작이 객체로 저장되는 실행 취소/다시 실행 시스템처럼 생각하면 됩니다.

코드를 두 개의 파일로 구성합니다:

  • commands.dart: 여기에서 명령 시스템을 만듭니다. execute() 메서드를 선언하는 추상 클래스 Command부터 시작하세요. 그런 다음 String content 필드(처음에는 비어 있음)를 가지고 세 가지 메서드를 갖는 TextDocument 클래스(수신자)를 만듭니다:
    • append(String text) - content 끝에 텍스트를 추가합니다.
    • clear() - content를 빈 문자열로 설정합니다.
    • show() - Document: [content]를 출력합니다.
    이제 TextDocument와 함께 작동하는 세 가지 구체적인 명령을 구현합니다:
    • AppendCommand - 생성자에서 문서와 텍스트를 받고, 실행될 때 텍스트를 추가합니다.
    • ClearCommand - 생성자에서 문서를 받고, 실행될 때 문서를 지웁니다.
    • ShowCommand - 생성자에서 문서를 받고, 실행될 때 그 내용을 보여줍니다.
    마지막으로, 명령 목록을 저장하는 TextEditor 클래스(호출자)를 만듭니다. 명령을 대기열에 추가하는 addCommand(Command command) 메서드와 대기열에 있는 모든 명령을 순서대로 실행하는 runAll() 메서드가 있어야 합니다.
  • main.dart: 명령 파일을 가져와서 Command 패턴을 시연합니다. TextDocumentTextEditor를 생성합니다. 다음 명령을 순서대로 대기열에 추가합니다: Hello 추가, World 추가, 문서 표시, ! 추가, 다시 표시, 문서 지우기, 마지막으로 한 번 더 표시. 그런 다음 대기열에 있는 모든 명령을 실행합니다.

TextEditor가 추가, 지우기 또는 표시에 대해 아무것도 모른다는 점에 주목하세요. 단지 주어진 명령을 실행할 뿐입니다. 이러한 결합 해제(decoupling)가 Command 패턴의 핵심입니다!

예상 출력:

Document: Hello World
Document: Hello World!
Document: 

직접 해보기

import 'commands.dart';

void main() {
  // TODO: TextDocument 인스턴스 생성

  // TODO: TextEditor 인스턴스 생성

  // TODO: 다음 명령들을 순서대로 큐에 추가:
  // 1. "Hello" 추가
  // 2. " World" 추가
  // 3. 문서 표시
  // 4. "!" 추가
  // 5. 문서를 다시 표시
  // 6. 문서 내용 지우기
  // 7. 문서를 마지막으로 한 번 더 표시

  // TODO: 대기열의 모든 명령 실행
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨