1. 개요
- 명령 디자인 패턴 (Command Design Pattern)은 명령(
Command
)을 객체로 만들고 실행 작업을 명령한 객체(Invoke
)와 실제 작업을 수행하는 객체(Receiver
) 사이의 의존성을 제거하고, 명령의 매개 변수를 조작하거나 취소, 재실행하는 등의 기능을 하는 패턴이다.
2. 상황
- 실행되는 작업을 객체로 캡슐화하고자 할 때
- 작업을 취소하거나 다시 실행해야 할 때
- 작업의 실행 순서를 관리해야 할 때
- 다양한 작업을 동적으로 구성해야 할 때
- 실행되는 작업과 호출하는 객체 간의 의존성을 줄여야 할 때
3. 다이어그램
3.1. 설명
Command
- 명령 추상 클래스이다.
Receiver
필드를 가진다.execute()
추상 메소드를 정의한다.
ConcreteCommand
Command
인터페이스의 구현 클래스이다.execute()
메소드를 구현을Receiver
에 위임한다.
Invoker
- 명령을 실행하는 객체이다.
- 요청을 수신하고, 해당 요청을
Command
객체에 전달하여 작업을 실행한다.
Receiver
- 실제 작업을 수행하는 객체이다.
- 명령에 의해 수행되어야 하는 작업이 구현되어 있다.
4. 구현
public abstract class Command {
protected Receiver receiver;
public Command(Receiver receiver) {
this.receiver = receiver;
}
public abstract void execute();
}
public class CommandA extends Command {
public CommandA(Receiver receiver) { super(receiver); }
@Override
public void execute() { receiver.operationA(); }
}
public class CommandB extends Command {
public CommandB(Receiver receiver) { super(receiver); }
@Override
public void execute() { receiver.operationB(); }
}
public class Invoker {
private List<Command> commands = new ArrayList<>();
public void add(Command c) { commands.add(c); }
public void start() {
for (Command c : commands) c.execute();
}
}
public class Receiver {
public void operationA() {
System.out.println("Receiver: Performing operationA");
}
public void operationB() {
System.out.println("Receiver: Performing operationB");
}
}
public class Client {
public static void main(String[] args) {
Invoker invoker = new Invoker();
invoker.add(new CommandA(new Receiver()));
invoker.add(new CommandB(new Receiver()));
invoker.start();
}
}
출력결과
Receiver: Performing operationA
Receiver: Performing operationB
5. 예시
public abstract class Command {
protected Player player;
public Command(Player player) { this.player = player; }
public abstract void execute();
}
class MoveCommand extends Command {
private int step;
public MoveCommand(Player player, int step) {
super(player); this.step = step;
}
@Override
public void execute() { player.move(step); }
}
class TurnCommand extends Command {
private Player.Direction dir;
public TurnCommand(Player player, Player.Direction dir) {
super(player); this.dir = dir;
}
@Override
public void execute() { player.turn(dir); }
}
class JumpCommand extends Command {
public JumpCommand(Player player) { super(player); }
@Override
public void execute() { player.jump(); }
}
public class Invoker {
List<Command> commands = new ArrayList<Command>();
void add(Command c) { commands.add(c); }
void start() {
for (Command c : commands) c.execute();
}
}
public class Player {
enum Direction { LEFT, RIGHT }
private String name;
public Player(String name) { this.name = name; }
void move(int step) { System.out.println(name + " moved " + step + " steps"); }
void jump() { System.out.println(name + " jumped"); }
void turn(Direction dir) { System.out.println(name + " turned " + dir.name()); }
}
public class Client {
public static void main(String[] args) {
Player player = new Player("Jane");
Invoker invoker = new Invoker();
invoker.add(new MoveCommand(player, 3));
invoker.add(new TurnCommand(player, Player.Direction.LEFT));
invoker.add(new JumpCommand(player));
invoker.start();
}
}
출력결과
Jane moved 3 steps
Jane turned LEFT
Jane jumped
6. 장단점
6.1. 장점
- 코드의 유연성과 확장성을 제공한다.
- 실행 취소(Undo)와 다시 실행(Redo) 기능 구현이 용이하다.
6.2. 단점
- 코드의 복잡성이 증가한다.
- 메모리 사용량이 증가한다.
관련 포스팅
728x90
'Develop > Design Pattern' 카테고리의 다른 글
[Design Pattern] 옵저버 (Observer) 패턴 (0) | 2023.11.14 |
---|---|
[Design Pattern] 메멘토 (Memento) 패턴 (0) | 2023.11.13 |
[Design Pattern] 경량 (Flyweight) 패턴 (0) | 2023.10.22 |
[Design Pattern] 중재자 (Mediator) 패턴 (0) | 2023.10.21 |
[Design Pattern] 인터프리터 (Interpreter) 패턴 (0) | 2023.10.18 |