Menu
Coddy logo textTech

커맨드 패턴

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

커맨드 패턴(Command Pattern)은 요청을 요청에 대한 모든 정보를 포함하는 독립형 객체로 변환하는 행동 디자인 패턴입니다. 이러한 변환을 통해 요청을 메서드 인수로 전달하거나, 요청의 실행을 지연 또는 대기열에 넣을 수 있으며, 취소 가능한 작업을 지원할 수 있습니다.

레스토랑을 생각해보세요.

음식을 주문할 때, 웨이터는 주문서(명령)에 주문 내용을 적어 주방으로 가져가고, 요리사가 이를 실행합니다. 웨이터는 요리하는 법을 알 필요가 없으며, 단지 명령을 전달할 뿐입니다.

이는 요청자를 실행자로부터 분리합니다.

기본적인 구현은 다음과 같습니다:

<?php
interface Command {
    public function execute(): string;
}
class Light {
    public function on(): string { return "Light is ON"; }
    public function off(): string { return "Light is OFF"; }
}
class LightOnCommand implements Command {
    public function __construct(private Light $light) {}
    
    public function execute(): string {
        return $this->light->on();
    }
}
class LightOffCommand implements Command {
    public function __construct(private Light $light) {}
    
    public function execute(): string {
        return $this->light->off();
    }
}

인보커(invoker)는 명령이 무엇을 하는지 모르는 상태에서 명령을 트리거합니다:

<?php
class RemoteControl {
    public function press(Command $command): string {
        return $command->execute();
    }
}
$light = new Light();
$remote = new RemoteControl();

echo $remote->press(new LightOnCommand($light)) . "\n";
echo $remote->press(new LightOffCommand($light));

출력:

Light is ON
Light is OFF

커맨드 패턴은 작업을 큐에 넣거나, 실행 취소 기능을 구현하거나, 작업을 기록해야 할 때 탁월합니다. 각각의 커맨드는 독립적이므로, 기존 코드를 수정하지 않고도 새로운 커맨드를 쉽게 추가할 수 있습니다.

challenge icon

챌린지

쉬움

커맨드 패턴(Command Pattern)을 사용하여 텍스트 에디터 커맨드 시스템을 구축해 봅시다. 텍스트 에디터는 텍스트 쓰기, 삭제, 실행 취소와 같은 작업을 지원해야 하는 경우가 많습니다. 각 작업은 통합된 인터페이스를 통해 실행될 수 있는 독립적인 커맨드 객체가 됩니다.

코드는 다음 네 개의 파일로 구성됩니다:

  • Command.php — 단일 메서드 execute(): string을 가진 Command 인터페이스를 정의합니다. 이는 모든 에디터 커맨드가 따라야 할 계약을 설정합니다.
  • TextEditor.php — 실제 작업을 수행하는 객체인 수신자(receiver)를 나타내는 TextEditor 클래스를 생성합니다. 에디터는 다음을 수행해야 합니다:
    • 현재 텍스트 콘텐츠를 저장합니다 (빈 문자열로 시작).
    • 콘텐츠에 텍스트를 추가하고 "Written: [text]"를 반환하는 write(string $text): string 메서드를 가집니다.
    • 콘텐츠를 비우고 "Content cleared"를 반환하는 clear(): string 메서드를 가집니다.
    • 현재 콘텐츠를 반환하는 getContent(): string 메서드를 가집니다.
  • Commands.php — Command 및 TextEditor 파일을 포함합니다. Command 인터페이스를 구현하는 두 개의 커맨드 클래스를 생성합니다:
    • WriteCommand — 생성자에서 TextEditor와 텍스트 문자열을 받습니다. execute() 메서드는 에디터의 write() 메서드를 호출하고 그 결과를 반환합니다.
    • ClearCommand — 생성자에서 TextEditor를 받습니다. execute() 메서드는 에디터의 clear() 메서드를 호출하고 그 결과를 반환합니다.
  • main.php — Commands 파일을 포함합니다. 두 개의 입력을 받습니다: 커맨드 타입("write" 또는 "clear")과 텍스트 문자열(쓰기 커맨드에만 사용됨).

    TextEditor 인스턴스를 생성합니다. 커맨드 타입에 따라 적절한 커맨드 객체를 생성합니다. 그런 다음 커맨드의 execute()를 호출하고 결과를 출력하는 인보커(invoker) 함수 또는 간단한 메커니즘을 만듭니다.

    새 줄에 에디터의 현재 콘텐츠를 Content: [content] 형식으로 출력합니다 (비어 있는 경우 공백 뒤에 아무것도 없이 Content:만 출력합니다).

이 챌린지는 커맨드 패턴이 각 작업을 객체로 캡슐화하는 방법을 보여줍니다. 인보커는 쓰기 커맨드를 실행하는지 지우기 커맨드를 실행하는지 알 필요가 없습니다. 단순히 execute()를 호출하고 커맨드가 세부 사항을 처리하도록 합니다.

치트 시트

커맨드 패턴(Command Pattern)은 요청을 요청에 대한 모든 정보를 포함하는 독립적인 객체로 캡슐화하는 행동 디자인 패턴입니다. 이를 통해 요청을 메서드 인수로 전달하고, 작업을 대기열에 추가하며, 실행 취소 가능한 작업을 지원할 수 있습니다.

이 패턴은 웨이터가 요리하는 법을 알 필요 없이 요리사에게 주문을 전달하는 방식과 유사하게, 요청자(invoker)와 실행자(receiver)를 분리합니다.

기본 구조

execute() 메서드를 가진 Command 인터페이스를 정의합니다:

interface Command {
    public function execute(): string;
}

실제 작업을 수행하는 수신자(receiver) 클래스를 생성합니다:

class Light {
    public function on(): string { return "Light is ON"; }
    public function off(): string { return "Light is OFF"; }
}

특정 작업을 캡슐화하는 구체적인 커맨드 클래스들을 구현합니다:

class LightOnCommand implements Command {
    public function __construct(private Light $light) {}
    
    public function execute(): string {
        return $this->light->on();
    }
}

class LightOffCommand implements Command {
    public function __construct(private Light $light) {}
    
    public function execute(): string {
        return $this->light->off();
    }
}

호출자 (Invoker)

호출자는 구현 세부 사항을 알지 못한 채 커맨드를 실행합니다:

class RemoteControl {
    public function press(Command $command): string {
        return $command->execute();
    }
}

$light = new Light();
$remote = new RemoteControl();

echo $remote->press(new LightOnCommand($light)) . "\n";
echo $remote->press(new LightOffCommand($light));

장점

커맨드 패턴은 작업 대기열 생성, 실행 취소 기능 구현 또는 작업 로깅에 이상적입니다. 각 커맨드는 독립적이므로 기존 코드를 수정하지 않고도 새로운 커맨드를 쉽게 추가할 수 있습니다.

직접 해보기

<?php

require_once 'Commands.php';

// 입력 읽기
$commandType = trim(fgets(STDIN)); // "write" 또는 "clear"
$text = trim(fgets(STDIN));         // write 명령을 위한 텍스트

// TODO: TextEditor 인스턴스 생성

// TODO: 명령 유형에 따라 적절한 명령 객체 생성
// - "write"인 경우, editor와 text를 사용하여 WriteCommand 생성
// - "clear"인 경우, editor를 사용하여 ClearCommand 생성

// TODO: 명령의 execute()를 호출하고 결과를 출력하는
// 인보커(invoker) 메커니즘 생성

// TODO: 에디터의 현재 내용을 다음 형식으로 출력: "Content: [content]"
// (비어 있는 경우, 공백 뒤에 아무것도 없이 "Content: "만 출력)

?>
quiz icon실력 점검

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

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