반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
Tags
- 싱글톤
- kafka
- 스프링부트
- JPA
- 스프링 부트 입문
- @Configuration
- 스프링 부트 기본
- Effective Java
- resultMap
- DI
- 스프링 빈
- Javascript
- spring
- 스프링
- java
- jdbc
- assertThrows
- 생성자 주입
- assertThat
- 스프링 프레임워크
- SQL
- db
- 스프링 컨테이너
- 스프링 부트
- thymeleaf
- sqld
- mybatis
- DIP
- 필드 주입
- springboot
Archives
- Today
- Total
선 조치 후 분석
[Design Pattern] 행동패턴 - Command 본문
728x90
반응형
SMALL
커맨드 (Command) 패턴
- 요청을 캡슐화하여 호출자(Invoker)와 수신자(Receiver)를 분리(의존성 제거) 하는 패턴
사용하는 이유?
- 호출자(Invoker) 객체가 수신자 (Receiver) 객체의 기능을 직접 호출한다면, 호출자에서 응답자 메소드를 호출하는
- 부분을 수정하거나 응답자의 코드가 수정되면 한쪽이 수정되더라도 양쪽 모두 수정이 되는 의존도가 높은 상태이다.
- 즉, 이 2개의 객체간 의존성을 제거하고 유연성을 확복하기 위함이다.
구조
- Invoker : Command에 기능을 실행해달라고 요청하는 호출자 클래스
- Command : ConcreateCommand의 실행 기능에 대한 인터페이스로 실행은 execute, 취소는 undo 같은 메소드로 선언
- ConcreateCommand : 실제로 실행되는 기능을 구현
- Receiver : ConcreateCommand에서 기능을 구현하기위해 필요한 클래스

커맨드 (Command) 패턴 적용 전
public class Button { // 호출자 - Invoker
private Light light;
public void press() {
light.on();
}
public Button(Light light) {
this.light = light;
}
}
public class Light { // 수신자 - Receiver
private boolean isOn;
public void on() {
System.out.println("불을 켭니다.");
this.isOn = true;
}
}
- Button이 호출자(Invoker)가 되어 Light 객체 (Receiver)의 기능을 호출한다
@Test
void test1() {
Button button = new Button(new Light());
button.press();
}
이 상황에서 "불을 끕니다." 라는 문구를 표시하는 새로운 메소드를 추가하려면 어떻게 될까?
- 요구사항으로 인한 Receiver 객체 코드 수정
public class Light { // 수신자 - Receiver
private boolean isOn;
public void on() {
System.out.println("불을 켭니다.");
this.isOn = true;
}
// 요구사항으로 새로운 메소드 추가 -> 코드 수정 발생
public void off() {
System.out.println("불을 끕니다.");
this.isOn = false;
}
}
- 요구사항으로 Invoker 객체 코드 수정
public class Button { // 호출자 - Invoker
private Light light;
public void press() {
// light.on();
// '불을 끈다' 라는 요구사항으로 코드 수정 필요
light.off();
}
public Button(Light light) {
this.light = light;
}
}
즉, 2개의 객체가 모두 수정이 필요한 상황이다. 호출자(Invoker)와 수신자(Receiver) 간의 의존성을 제거하기 위해
커맨드 (Command) 패턴을 사용한다.
커맨드 (Command) 패턴 적용 후
- 실행되는 행위를 캡슐화
- 버튼을 누를 때 어떤 행동을 할 지, Command 인터페이스를 통해 호출
- 행위를 추상화하고, 내부 기능을 캡슐화 함으로써 호출자(Invoker)는 수신자(Receiver)의 구체적인 사항을 몰라도
된다. (의존성 분리)
public interface Command {
void execute();
}
- Command을 구현하는 캡슐화 객체
public class LightOnCommand implements Command{
private Light light;
@Override
public void execute() {
light.on();
}
public LightOnCommand(Light light) {
this.light = light;
}
}
public class LightOffCommand implements Command{
private Light light;
@Override
public void execute() {
light.off();
}
public LightOffCommand(Light light) {
this.light = light;
}
}
- 호출자(Invoker)는 Command의 'execute' 메소드만 바라보고 구체적인 기능은 내부로 캡슐화 되어있다.
- 요구사항이 추가되거나 수정이되면 수신자(Receiver)의 구현체가 추가되거나 수정된다.
- 기능이 변경되더라도 호출자(Invoker)의 Command를 실행하는 부분은 수정이 일어나지 않는다.
- 즉, 수정 범위의 축소 그리고 Command 재사용성의 증가, 책임의 분리가 된다.
public class Button2 { // 호출자 - Invoker
// Command 객체 이용
private final Command command;
public Button2(Command command) {
this.command = command;
}
public void press() {
command.execute();
}
}
커맨드 (Command) 패턴
장점
- 기존 코드를 변경하지 않고 새로운 커맨드를 만들 수 있다.
- 수신자(Receiver)의 코드가 변경되어도 호출자(Invoker)의 코드는 변경되지 않는다.
- 커맨드 객체를 로깅, DB에 저장 및 네트워크로 전송하는 등 다양한 방법으로 활용할 수 있다
단점
- 클래스가 많아진다.
728x90
반응형
LIST
'Language > Design Pattern' 카테고리의 다른 글
[Design Pattern] 행동패턴 - Iterator (0) | 2023.11.06 |
---|---|
[Design Pattern] 행동패턴 - Interpreter (0) | 2023.11.01 |
[Design Pattern] 구조패턴 - Flyweight (0) | 2023.10.30 |
[Design Pattern] 구조패턴 - Facade (0) | 2023.10.30 |
[Design Pattern] 구조 패턴 - Decorator (0) | 2023.10.27 |