Menu
Coddy logo textTech

커맨드 패턴

Coddy Java 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 87개 중 70번째.

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

레스토랑을 예로 생각해 보세요. 요리사에게 무엇을 요리할지 직접 말하는 대신, 주문을 쪽지에 적습니다. 웨이터(invoker)가 그 쪽지(command)를 주방으로 가져가면, 주문을 대기열에 넣거나 우선순위를 지정하거나 심지어 취소할 수도 있습니다. 이 패턴은 작업을 호출하는 객체와 작업을 수행하는 객체를 분리합니다.

이 패턴에는 네 가지 핵심 구성 요소가 있습니다. execute method를 선언하는 Command interface, 특정 actions를 Implement하는 ConcreteCommand classes, actual 작업을 수행하는 Receiver, 그리고 commands를 트리거하는 Invoker입니다.

interface Command {
    void execute();
}
class Light {  // 수신자
    public void turnOn() {
        System.out.println("Light is ON");
    }
    public void turnOff() {
        System.out.println("Light is OFF");
    }
}
class LightOnCommand implements Command {
    private Light light;
    
    public LightOnCommand(Light light) {
        this.light = light;
    }
    
    public void execute() {
        light.turnOn();
    }
}
class RemoteControl {  // 호출자
    private Command command;
    
    public void setCommand(Command command) {
        this.command = command;
    }
    
    public void pressButton() {
        command.execute();
    }
}

invoker는 어떤 동작이 수행될지 알지 못합니다. 단지 execute()를 호출합니다:

Light light = new Light();
Command lightOn = new LightOnCommand(light);

RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton();  // 출력: Light가 켜졌습니다

Command Pattern은 작업을 대기열에 추가하거나, 실행 취소/다시 실행 기능을 구현하거나, 나중에 실행할 작업을 예약해야 할 때 특히 유용합니다. 각 command는 작업을 수행하는 데 필요한 모든 것을 encapsulate하므로 시스템을 더욱 유연하고 확장 가능하게 만들 수 있습니다.

challenge icon

챌린지

쉬움

Command 패턴을 사용하여 스마트 홈 자동화 시스템을 구축해 봅시다! 각 장치의 내부 작동 방식을 알 필요가 없는 범용 리모컨처럼, 다양한 가정용 장치를 명령을 통해 제어하고 작업을 대기열에 추가하거나 실행하며 나중에 사용할 수 있도록 저장할 수 있는 시스템을 만들게 됩니다.

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

  • Command.java: 모든 장치 명령이 구현할 Command interface를 정의합니다. 명령의 작업을 수행하는 단일 method execute()를 선언해야 합니다.
  • Devices.java: 스마트 홈 장치를 나타내는 두 개의 receiver class를 생성합니다:

    Television - TV is now ON을 출력하는 powerOn(), TV is now OFF를 출력하는 powerOff(), 그리고 TV channel set to [channel]을 출력하는 setChannel(int channel) method를 가집니다.

    Thermostat - Thermostat set to [temp] degrees를 출력하는 setTemperature(int temp) method와 Thermostat turned OFF를 출력하는 turnOff() method를 가집니다.

  • Commands.java: 장치 작업을 encapsulate하는 구체적인 명령 class를 생성합니다:

    TVOnCommand - constructor에서 Television을 전달받고, 실행될 때 powerOn()을 호출합니다.

    TVOffCommand - constructor에서 Television을 전달받고, 실행될 때 powerOff()를 호출합니다.

    TVChannelCommand - constructor에서 Televisionint channel을 전달받고, 실행될 때 해당 channel을 사용하여 setChannel()을 호출합니다.

    ThermostatSetCommand - constructor에서 Thermostatint temperature를 전달받고, 실행될 때 해당 값을 사용하여 setTemperature()를 호출합니다.

  • Main.java: 명령을 저장하는 setCommand(Command cmd) method와 저장된 명령을 실행하는 pressButton() method를 가진 RemoteControl class(invoker)를 생성합니다.

    main method에서 두 개의 input을 받습니다. 하나는 TV channel 번호(integer)이고, 다른 하나는 thermostat temperature(integer)입니다.

    TelevisionThermostat을 생성합니다. RemoteControl을 생성하고 다음과 같이 Command 패턴을 보여 줍니다:

    1. TVOnCommand를 설정하고 button을 누릅니다
    2. input channel을 사용하여 TVChannelCommand를 설정하고 button을 누릅니다
    3. input temperature를 사용하여 ThermostatSetCommand를 설정하고 button을 누릅니다
    4. TVOffCommand를 설정하고 button을 누릅니다

두 개의 input을 순서대로 받습니다: TV channel(integer)과 thermostat temperature(integer)입니다.

예를 들어 input이 572라면 출력은 다음과 같습니다:

TV is now ON
TV channel set to 5
Thermostat set to 72 degrees
TV is now OFF

RemoteControl은 장치와 직접 상호 작용하지 않는다는 점에 주목하세요. Command interface에 대해서만 알고 있습니다. 각 명령은 작업을 수행하는 데 필요한 모든 것을 encapsulate하므로, invoker를 변경하지 않고도 새로운 장치와 명령을 쉽게 추가할 수 있습니다!

직접 해보기

import java.util.Scanner;

// TODO: 다음을 포함하는 RemoteControl 클래스(invoker) 생성:
// - 명령을 저장하는 setCommand(Command cmd) 메서드
// - 저장된 명령을 실행하는 pressButton() 메서드

class RemoteControl {
    // TODO: RemoteControl 구현
}

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // 입력 읽기
        int channel = scanner.nextInt();
        int temperature = scanner.nextInt();
        
        // TODO: Television 및 Thermostat 생성
        
        // TODO: RemoteControl 생성
        
        // TODO: Command 패턴 시연:
        // 1. TVOnCommand를 설정하고 버튼 누르기
        // 2. 입력 채널로 TVChannelCommand를 설정하고 버튼 누르기
        // 3. Set a ThermostatSetCommand with the input temperature and press the button
        // 4. TVOffCommand를 설정하고 버튼 누르기
        
        scanner.close();
    }
}
quiz icon실력 점검

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

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

직접 연습해 보세요: 온라인 Java 컴파일러