<디자인패턴입문> 16. State 패턴
by BFine
www.yes24.com/Product/Goods/2918928
가. 무엇인가
a. 상태를 클래스로!
- 보통 프로그래밍할때 대상을 클래스로 표현하고 상태는 필드 행위는 메서드형태로 구성한다.
- 하지만 State(상태)패턴은 상태(사물의 모양이나 형편)을 클래스로 표현한다.
=> 클래스를 교체해 상태변화를 표현할 수 있고 새로운 상태 추가할때 무엇을 해야할지 분명해진다.
b. 끝없는 if-else
- 책에 있는 경비시스템에 대한 예제를 살펴보자. 틀린방법은 아니지만 메서드안에 if-else가 각각 들어간다.
- 상태가 늘어날경우 모든 메서드에 if else 또한 반복되어져서 나오게 된다.
=> 만약 주간,야간이 아니라 한시간 단위라고 하면 각각 메서드에 24개의 분기처리를 반복처리해야한다.
class 경비시스템{
금고사용(){
if(주간){
...
}else if(야간){
...
}
}
일지작성(){
if(주간){
...
}else if(야간){
...
}
}
}
- State패턴을 적용하여 상태를 관점으로 하는 클래스를 구현하면 상태검사를 위한 if-else가 등장하지 않는다.
class 주간{
금고사용(){
...
}
일지작성(){
...
}
}
class 야간{
금고사용(){
...
}
일지작성(){
...
}
}
나. 만들어본 예제
a. State(상태)의 역할
- 상태에 따라서 각각 동작하는 인터페이스를 작성한다.
public interface EmotionState {
EmotionState behavior();
}
b. ConcreteState(구체적인 상태)의 역할
- 구체적인 상태를 각각 표현한다.
- 예제에서 화는 슬픔을 부른다는 것을 클래스를 변경함으로써 상태전환을 표현해보았다.
=> 현재상태를 나타내는 필드에 상태를 나타내는 클래스의 인스턴스를 대입하는 것이 상태전환이다.
public class AngryState implements EmotionState{
@Override
public EmotionState behavior() {
System.out.println("버럭이 : 모니터를 때립니다.");
System.out.println("버럭이 : 모니터 액정이 깨졌습니다.");
return new SadState();
}
}
public class HappyState implements EmotionState{
@Override
public EmotionState behavior() {
System.out.println("행복이 : 웃고있습니다.");
return this;
}
}
public class SadState implements EmotionState{
@Override
public EmotionState behavior() {
System.out.println("슬픔이 : 울고있습니다.");
return this;
}
}
c. Context(상황, 전후관계, 문맥)의 역할
- 현재의 상태를 나타내며 그 상태에 맞는 ConcreteState의 행위를 결정하는 역할을 한다.
=> 예제는 현재상태를 나타내는 역할만 하고 있다.
public class HumanContext {
private EmotionState emotionState;
public HumanContext(EmotionState emotionState) {
this.emotionState = emotionState;
}
public void behavior(){
emotionState = emotionState.behavior();
}
public void setEmotionState(EmotionState emotionState) {
this.emotionState = emotionState;
}
}
d. Main
public class HumanContext {
private EmotionState emotionState;
public HumanContext(EmotionState emotionState) {
this.emotionState = emotionState;
}
public void behavior(){
emotionState = emotionState.behavior();
}
public void setEmotionState(EmotionState emotionState) {
this.emotionState = emotionState;
}
}
/**
"C:\Program Files\Java\jdk1.8.0_251\bin\java.exe"
행복이 : 웃고있습니다.
버럭이 : 모니터를 때립니다.
버럭이 : 모니터 액정이 깨졌습니다.
슬픔이 : 울고있습니다.
*/
다. 정리
a. 분할해서 통치해라
- Divide and Conquer 은 복잡하고 규모가 큰 프로그램을 취급할 경우 방침이다.
=> 규모가 크고 복잡한 문제는 그대로 해결할려고 하면 안된다!
- 문제를 간단하게 해결할때까지 작게 나누어서 해결해야한다.
=> State 패턴에서는 상태를 클래스로 표현해서 문제를 분할한 것이다.
=> 내가 구현할 상태(ConcreteState) 클래스에만 집중할 수 있는 장점이 있다.
b. 상태전환은 누가 관리해야 하나?
- State 패턴을 사용할때 상태전환은 누가 관리해야 하는지 주의해야한다.
- 예제는 상태전환을 상태클래스에서 하고 있다. 즉 상태에 의존한 동작으로 간주하고 있다.
- 장점
- 다른 상태로의 전환하는 것은 언제인가 하는 정보가 클래스내에 정리 되어있다.
- 단점
- 하나의 상태클래스의 역할이 다른상태클래스의 역할을 알아야하는 문제가 있다.
=> Sad 클래스를 삭제하면 Angry 클래스도 수정해야한다.
- 다른 방법으로는 Context에게 모든 상태전환을 맡기는 것이다.
- 장점
- ConcreteState 역할의 독립성이 높아져 전체 예측이 좋아질 수 있다.
- 단점
- Context 역할이 모든 ConcreteState 역할을 알아햐 하는 단점이 있다.
c. State 패턴의 장단점
- 장점
- 새로운 상태를 추가할때 상태 클래스만 추가하기만 하면 된다.
- 어떤 메서드를 만들어야하는지가 명확해진다.
- 단점
- State 역할에 새로운 인터페이스를 추가하는 경우 모든 상태클래스에 구현해야한다.
상태패턴은 상태를 클래스로 나타내서 상태변경을 인스턴스 변경으로 표현하는 패턴이다.
'개발서적 > 디자인패턴입문' 카테고리의 다른 글
<디자인패턴입문> 18. Proxy 패턴 (0) | 2021.05.11 |
---|---|
<디자인패턴입문> 17. Flyweight 패턴 (0) | 2021.05.10 |
<디자인패턴입문> 15. Memento 패턴 (0) | 2021.05.08 |
<디자인패턴입문> 14. Observer 패턴 (0) | 2021.05.07 |
<디자인패턴입문> 13. Mediator 패턴 (0) | 2021.05.06 |
블로그의 정보
57개월 BackEnd
BFine