티스토리 뷰

디자인 패턴

14. 커맨드 패턴

jin-park 2022. 2. 10. 20:13

1. 커맨드 패턴

  • 요청을 캡슐화 하여 호출자(invoker)와 수신자(receiver)를 분리하는 패턴
    • 요청을 처리하는 방법이 바뀌더라도, 호출자의 코드는 변경되지 않는다.

다이어그램

  • Invoker : 호출자
  • Command
    • 수신자가 어떤 클래스이고, 수신자가 어떤 명령을 호출해야하는지 명시
    • 명령을 수행하기 위한 모든 작업들을 캡슐화, 재사용 용이
    • 여러 구체적인 커맨드들을 구체화
  • Receiver : 수신자
  • ConcreteCommand : 구현체,  어떠한 수신자를 사용할지, 수신자의 명령 및 파라미터들을 명시

2. 커맨드 패턴 적용 전

  • 호출자쪽에  비슷한 코드가 중복되는 문제 > 호출자와 수신자간의 관계가 타이트하여 발생
  • 호출자쪽에서 다른 명령을 실행하고 싶다면, 코드를 또 변경해야하는 상황이 발생
public class Game {
 
    private boolean isStarted;
 
    public void start() {
        System.out.println("게임을 시작합니다.");
        this.isStarted = true;
    }
 
    public void end() {
        System.out.println("게임을 종료합니다.");
        this.isStarted = false;
    }
 
    public boolean isStarted() {
        return isStarted;
    }
}
public class Button {
 
    private Game game;
 
    public Button(Game game) {
        this.game = game;
    }
 
    public void press() {
    	if (game.isStarted()) {
        	game.end();
        } else {
        	game.start();
        }
    }
 
    public static void main(String[] args) {
        Button button = new Button(new Game());
        button.press();
        button.press();
        button.press();
        button.press();
    }
}

3. 커맨드 패턴 적용 후

public interface Command {
    void execute();
    void undo(); //undo 기능 추가
}
public class GameStartCommand implements Command {
 
    private Game game;
 
    public GameStartCommand(Game game) {
        this.game = game;
    }
 
    @Override
    public void execute() {
        game.start();
    }
 
    //undo 기능 추가
    @Override
    public void undo() {
        new GameEndCommand(this.game).execute();
    }
}
public class GameEndCommand implements Command {
 
    private Game game;
 
    public GameEndCommand(Game game) {
        this.game = game;
    }
 
    @Override
    public void execute() {
        game.end();
    }
 
    //undo 기능 추가
    @Override
    public void undo() {
        new GameStartCommand(this.game).execute();
    }
}
public class Button {
 
    private Command command;
 
    public Client(Command command) {
        this.command = command;
    }
 
    public void press() {
        command.execute();
    }
    
    public void undo() {
        command.undo();
    }
 
    public static void main(String[] args) {
        Button button = new Button(new GameStartCommand(new Game()));
        button.press();
        button.undo();
        
        Button button2 = new Button(new GameEndCommand(new Game()));
        button2.press();
        button2.undo();
    }
}

4. 장점 및 단점

4.1. 장점

  • 기존 코드를 변경하지 않고 새로운 커맨드를 만들 수 있다.
  • 수신자의 코드가 변경되어도 호출자의 코드는 변경되지 않는다.
  • 커맨드 객체를 로깅, DB에 저장, 네트워크로 전송하는 등 다양한 방법으로 활용할 수 도 있다.

4.2. 단점

  • 코드가 복잡하고 클래스가 많아진다.

위글은 인프런의 코딩으로 학습하는 GoF의 디자인 패턴강의를 정리하였습니다.

백기선님의 수락으로 정리하였으며 더 자세한 내용은 강의를 수강하시기 바랍니다.

https://www.inflearn.com/course/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4/dashboard

 

코딩으로 학습하는 GoF의 디자인 패턴 - 인프런 | 강의

디자인 패턴을 알고 있다면 스프링 뿐 아니라 여러 다양한 기술 및 프로그래밍 언어도 보다 쉽게 학습할 수 있습니다. 또한, 보다 유연하고 재사용성이 뛰어난 객체 지향 소프트웨어를 개발할

www.inflearn.com

 

'디자인 패턴' 카테고리의 다른 글

16. 이터레이터 패턴  (0) 2022.02.10
15. 인터프리터 패턴  (0) 2022.02.10
13. 책임연쇄패턴  (0) 2022.02.10
12. 프록시 패턴  (0) 2022.02.10
11. 플라이 웨이트 패턴  (0) 2022.02.10
댓글