Updated:

1. 개요

요청 자체를 캡슐화 하여 요청의 대기, 로깅, 취소 연산을 지원하는 패턴

명령 패턴(Command Pattern)은 행동 패턴(Behavioral Pattern)의 한 종류로, 명시되지 않은 객체의 요청을 처리할 수 있도록 지원하는 패턴이다. Command 인터페이스에 요청을 처리하기 위한 메서드 하나만을 정의하고, Command 서브클래스에서 Receiver 객체를 전달받아 Receiver 객체에 정의된 기능을 수행한다.

2. 행동 패턴(Behavioral Pattern)

2-1. 행동 패턴이란?

행동 패턴이란 처리의 책임을 어떤 객체에게 할당하는 것이 좋은지, 알고리즘을 어떤 객체에 정의하는 것이 좋은지 등의 책임 분배와 관련된 패턴이다.

2-2. 행동 패턴 종류

3. 구성

[출처 : GoF의 디자인 패턴]

  • Command : 요청을 처리하기 위한 메서드가 정의된 인터페이스

  • ConcreteCommand : Receiver 객체를 연결하고, 해당 객체에 정의된 연산을 호출하도록 Command 인터페이스 구현

  • Invoker : Command 클래스에게 명령 처리를 요청하는 클래스

  • Receiver : 요청에 관련된 연산 수행 방법을 알고있는 클래스

  • Client : ConcreteCommand 객체를 생성하고, Receiver 객체를 전달

4. 예제 코드

Command Pattern을 이용하여 TV의 Volume을 올리고 내리는 코드를 구현해보자. Command Pattern을 이용하면 TV뿐만 아니라 컴퓨터, 핸드폰 등 다양한 객체에 대해 기능을 손쉽게 확장할 수 있다.

4-1. Invoker

[Button.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Button {

    private Command upCommand;
    private Command downCommand;

    public Button(Command upCommand, Command downCommand) {
        this.upCommand = upCommand;
        this.downCommand = downCommand;
    }

    public void up() {
        upCommand.execute();
    }

    public void down() {
        downCommand.execute();
    }
}

4-2. Receiver

[Tv.java]

1
2
3
4
5
6
7
8
9
10
public class Tv {

    public void volumeUp() {
        System.out.println("TV volume up");
    }

    public void volumeDown() {
        System.out.println("TV volume down");
    }
}

4-3. Command

[Command.java]

1
2
3
4
public interface Command {

    void execute();
}

4-4. ConcreteCommand

[VolumeUpTvCommand.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
public class VolumeUpTvCommand implements Command {

    private Tv tv;

    public VolumeUpTvCommand(Tv tv) {
        this.tv = tv;
    }

    @Override
    public void execute() {
        tv.volumeUp();
    }
}

[VolumeDownTvCommand.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
public class VolumeDownTvCommand implements Command {

    private Tv tv;

    public VolumeDownTvCommand(Tv tv) {
        this.tv = tv;
    }

    @Override
    public void execute() {
        tv.volumeDown();
    }
}

5. 테스트

[Clinet.java]

1
2
3
4
5
6
7
8
9
10
11
12
public class Client {

    public static void main(String[] args) {
        Tv tv = new Tv();
        Command upButton = new VolumeUpTvCommand(tv);
        Command downButton = new VolumeDownTvCommand(tv);

        Button button = new Button(upButton, downButton);
        button.up();
        button.down();
    }
}

[실행 결과]

6. 특징

  • 객체의 분리 : 연산을 호출하는 객체와 연산을 구현하는 객체의 분리

  • 일관된 방식으로 확장 : Command 인터페이스를 통해 같은 방식으로 확장 가능

  • 유연한 확장 : 기존 코드를 수정하지 않고, 새로운 기능 추가 가능(OCP)

Updated:

Leave a comment