반응형
커맨드 패턴이란?
커맨드를 객체로 만들어서 이를 사용해 나중에 실행하거나, 반복하거나 취소할 수 있도록 하는 패턴이다.
현실에서는 음식점에 손님으로 방문해 주문을 하면 주방에 주문서를 꽂아놓는다. 요리사는 이를 보고 요리를 한다. 주문서에는 음식과 관련된 모든 정보를 가지고 있다. 이때 이 주문서가 커맨드 역할을 하는것 이다.
왜 사용해야 하는가?
- 클라이언트는 요청을 객체로 표현하기 때문에 수신자에게 직접적으로 의존하지 않게 된다.
- 실행 취소 및 재 실행 기능을 쉽게 구현할 수 있다.
- 간단한 커맨드들로 복잡한 커맨드를 조합할 수 있다.
- 기존의 코드를 건들지 않고 새 커맨드를 추가할 수 있다.
언제 사용해야 하는가?
- 요청과 수신자를 분리하고 싶을 때
- 요청의 로깅이 필요할 때
- 늦게 실행하거나 실행 취소 및 재실행기능이 필요할 때
구현 예시(자바)
기초적인 단계로 커맨드 부분만 구현해 보도록 하겠다.
자바 콘솔창에서 문자를 추가하거나 색상을 바꿔보도록 하겠다.
먼저 커맨드 인터페이스를 만들어주자.
package com.example.designpattern.behavioral.commandv2.command;
public interface Command {
void run();
}
- run에는 앞으로 커맨드가 실행하는 메서드들을 구현할 것이다.
해당 인터페이스를 토대로 색상을 변경하는 커맨드와 문자를 출력하는 커맨드를 추가해 주었다.
package com.example.designpattern.behavioral.commandv2.command;
public class ColorCommand implements Command {
public enum Color {
BLACK("\u001B[30m"), RED("\u001B[31m"),
GREEN("\u001B[32m"), YELLOW("\u001B[33m"),
BLUE("\u001B[34m"), PURPLE("\u001B[35m"),
CYAN("\u001B[36m"), WHITE("\u001B[37m");
private final String code;
Color(String code) {
this.code = code;
}
public String getCode() {
return code;
}
}
private Color color;
public ColorCommand(Color color) {
this.color = color;
}
@Override
public void run() {
System.out.print(color.getCode());
}
}
package com.example.designpattern.behavioral.commandv2.command;
import com.example.designpattern.behavioral.commandv2.command.Command;
public class PrintCommand implements Command {
private String content;
public PrintCommand(String content) {
this.content = content;
}
@Override
public void run() {
System.out.println(content);
}
}
그 뒤에 커맨드들을 담고 있을 커맨드그룹을 생성해 주었다.
package com.example.designpattern.behavioral.commandv2.command;
import java.util.ArrayList;
import java.util.List;
public class CommandGroup implements Command {
private List<Command> commands = new ArrayList<>();
public void add(Command command) {
commands.add(command);
}
public Command pop(){
int last = commands.size() - 1;
Command popCommand = commands.get(last);
commands.remove(last);
return popCommand;
}
@Override
public void run() {
int size = commands.size();
for (Command command : commands) {
command.run();
}
}
}
이제 클라이언트들은 실행했던 명령들을 손쉽게 반복하고 명령을 취소했다가 다시 실행시킬 수 있게 되었다.
package com.example.designpattern.behavioral.commandv2;
import com.example.designpattern.behavioral.commandv2.command.ColorCommand;
import com.example.designpattern.behavioral.commandv2.command.Command;
import com.example.designpattern.behavioral.commandv2.command.CommandGroup;
import com.example.designpattern.behavioral.commandv2.command.PrintCommand;
public class CommandClient {
public static void main(String[] args) {
CommandGroup commandGroup = new CommandGroup();
PrintCommand printCommand = new PrintCommand("안녕하세요!");
commandGroup.add(new ColorCommand(ColorCommand.Color.GREEN));
commandGroup.add(printCommand);
commandGroup.add(new ColorCommand(ColorCommand.Color.RED));
commandGroup.add(printCommand);
commandGroup.add(printCommand);
commandGroup.add(new ColorCommand(ColorCommand.Color.CYAN));
commandGroup.add(printCommand);
commandGroup.run();
System.out.println("===== 명령 취소 해보기 =====");
Command popCommand = commandGroup.pop();
commandGroup.run();
System.out.println("==== 취소한 명령 다시 실행하기 ====");
commandGroup.add(popCommand);
commandGroup.run();
}
}
실행결과
- 결과를 보면 마지막 실행을 취소했다가 다시 실행하는 것을 볼 수 있다.
반응형
'Design Pattern > 행동 패턴(Behavioral patterns)' 카테고리의 다른 글
Observer Pattern, 옵저버 패턴 (0) | 2024.04.01 |
---|---|
Memento Pattern, 메멘토 패턴 (1) | 2024.03.27 |
Mediator Pattern, 중재자 패턴 (2) | 2024.03.07 |
Iterator Pattern, 반복자 패턴 (0) | 2024.02.28 |
Chain of Responsibility Pattern, 책임 연쇄 패턴 (0) | 2024.02.27 |