개발/디자인패턴

[Java][디자인 패턴] 15. 명령 패턴 (Command Pattern)

nova_dev 2022. 3. 19. 00:00
반응형

디자인패턴
[Java][디자인 패턴] 15. 명령 패턴 (Command Pattern)

명령 패턴은 행동의 호출을 객체로 캡슐화하여 실행하는 패턴이다.

 명령 패턴이란?

  • 작업하는 동작 자체를 다른 객체에 전달하는 경우 사용한다.
  • 행동을 객체로 캡슐화한다.
  • 유사한 동작을 하나의 객체로 묶어 실행하는 행위 패턴이다.
  • 실제 작업을 수행하는 객체와 이를 실행하는 객체로 분리하여 설계한다.
  • 객체의 실행 동작 시점을 분리시켜 지연시키는데, 이는 절차 지향적 개발에서 콜백 함수를 처리하는 것과 같다. (객체지향적인 콜백 처리)
  • 명령 패턴은 요청과 실행이 서로 의존하지 않는 구조를 만들 때 유용하다.

 

 

 명령 패턴 구조

  • Command
    • 추상화된 명령 (execute와 같은)을 인터페이스로 선언한다.
    • 모든 명령들이 공통적으로 동일한 명령 구조와 호출을 하기 위한 인터페이스이다.
  • ConcreteCommand
    • 명령으로 실행되는 실제 객체를 구현한다.
    • 명령 객체의 execute() 메서드는 실제 객체의 실행을 호출하는 방아쇠 역할을 한다. (Receiver로 받아온 실제 객체의 명령(action)들을 수행함)
    • 명령 객체를 생성할 때 실행 동작을 직접 구현하는 것과 달리 외부로부터 객체를 위임받아 대신 호출한다.
  • Receiver
    • 부분 부분의 Command를 실제로 실행하는 방법을 아는 클래스이다. (action1,2..)
    • 명령 패턴은 처리해야 하는 명령을 하나의 객체로 캡슐화한다.
  • Invoker
    • 다수의 명령 객체를 관리한다. (명령 객체를 담고 있는 배열)
    • 생성된 명령 객체를 저장하고 관리하는 역할을 한다.
    • 실제 동작의 리시버 객체를 저장한다.
    • 저장된 명령 객체의 요청을 실행하고 명령 객체의 execute() 메서드를 대신 호출한다. (마치 인보커에 등록된 모든 명령 객체를 한번에 수행할 수 있는 메크로)
    • 반복자 패턴 결합
  • Client
    • 명령 패턴에서 새로운 명령 객체를 생성하고 생성된 명령 객체를 다시 리시버에 전달하며 인보커에 저장된 명령 객체 실행을 요청한다.

 명령 패턴 예제 코드 구조

(**짭주의**) 빅스바에서 '음악 틀어줘' 라는 명령을 내릴 때 실행할 수 있는 어플리케이션에 '플라'와 '우투브'가 있다고 해보자. 음악은 틀어달라는 명령은 동일하지만, 실제로 실행하는 객체들은 각각 다르다. 이런 경우 명령 패턴을 사용하기 좋다.

 명령 패턴 코드

1. Music 인터페이스

public interface Music {
    void musicOn();

    void musicOff();
}

2. Music 인터페이스를 구현하는 Fla 클래스와 Utube 클래스

public class Fla implements Music {
    @Override
    public void musicOn() {
        System.out.println("플라에서 음악을 재생합니다.");
    }

    @Override
    public void musicOff() {
        System.out.println("플라에서 음악을 끕니다.");
    }
}
public class Utube implements Music {
    @Override
    public void musicOn() {
        System.out.println("우투브에서 음악을 재생합니다.");
    }

    @Override
    public void musicOff() {
        System.out.println("우투브에서 음악을 끕니다");
    }
}

3. CommandType enum 클래스

public enum CommandType {
    COMMAND_MUSIC_ON("COMMAND_MUSIC_ON", "음악 켜줘"),
    COMMAND_MUSIC_OFF("COMMAND_MUSIC_ON", "음악 꺼줘"),
    ;
    private final String code;
    private final String value;


    CommandType(String code, String value) {
        this.code = code;
        this.value = value;
    }

    public String getCode() {
        return code;
    }

    public String getValue() {
        return value;
    }
}

4. 음악 명령을 실행하는 BixBa 클래스

public class BixBa {
    private Music music;

    public BixBa(Music defaultMusic) {
        this.music = defaultMusic;
    }

    public void talk(CommandType commandType) {
        switch (commandType) {
            case COMMAND_MUSIC_ON:
                music.musicOn();
                break;
            case COMMAND_MUSIC_OFF:
                music.musicOff();
                break;
            default:
                System.out.println("빅스바는 잘 모르는 내용이에요. 다시 한번 말해주세요.");
        }
    }
}

5. 빅스바 테스트 코드

class BixBaTest {

    @Test
    @DisplayName("빅스바 음악 플라")
    void musicFlaTest() {
        BixBa bixBa = new BixBa(new Fla());
        bixBa.talk(CommandType.COMMAND_MUSIC_ON);
        bixBa.talk(CommandType.COMMAND_MUSIC_OFF);
    }

    @Test
    @DisplayName("빅스바 음악 우투브")
    void musicUtubeTest() {
        BixBa bixBa = new BixBa(new Utube());
        bixBa.talk(CommandType.COMMAND_MUSIC_ON);
        bixBa.talk(CommandType.COMMAND_MUSIC_OFF);
    }
}

 Github 코드

Github 예제 코드 링크

Github 예제 테스트 코드 링크

참고 자료

 

 

 

 

 

반응형