세줄 정리

  • 상태에 따라서 다르게 동작해야할 때
  • 케이스가 추가될 때마다 코드를 수정하는 것이 복잡해짐
  • 상태를 각각의 클래스로 만들고, 각 상태에서 메서드를 제공

디자인 패턴 적용 안한경우

단점

  • if else 구문을 사용하기 때문에, 상태가 추가될 경우, VendingMachine 클래스 수정해줘야함
    (이를 개방 폐쇄의 원칙에 어긋난다고 합니다.)
  • if else 구문을 추가해주고, 그때의 메소드를 추가

상황

  • 자판기 소프트웨어에서
  • 제품이 판매 가능하면 상품이 나오고,
  • 제품이 매진되었으면 상품이 나오지 않고 빨간 불빛을 표시

if else로 구현할 경우

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class VendingMachine {
private String state = “AVAILABLE”; // SOLDOUT or AVAILABLE
    
    public void select() {
        if(state.equals(“AVAILABLE”)) provideProduct();
        else if(state.equals(“SOLDOUT”)) redRight();
    }
 
    private void provideProduct() {
        ...
    }
 
    private void redRight() {
        ...
    }
}
 
cs

제품이 한개 남았을때는 초록색 불빛 기능 추가 될때

1
2
3
4
5
6
7
8
9
10
11
public class VendingMachine {
private String state = “AVAILABLE”; // SOLDOUT or AVAILABLE or ONELEFT
    
    public void select() {
        if(state.equals(“AVAILABLE”)) provideProduct();
        else if(state.equals(“SOLDOUT”)) redRight();
        else if(state.equals(“ONELEFT”)) greenRight();
    }
 
}
 
cs

상태 패턴

State Pattern UML

개념

  • 각각의 상태 객체가 기능을 제공
  • 콘텍스트는 상태 객체를 가지고, 상태 객체에서 기능을 실행

장점

  • 상태가 많아져 클래스 개수는 증가하지만, 코드의 복잡도는 증가하지 않음
  • 상태별 동작을 수정하기가 쉬움
    • if else의 경우 각각의 상태에서 실행하는 메소드를 찾아서 수정해줘야함

VendingMachine(Context)

1
2
3
4
5
6
7
8
9
10
11
12
public class VendingMachine {
    private State state;
 
    public VendingMachine(State state) {
        this.state = state;
    }
 
    public void select() {
        state.select();
    }
}
 
cs

상태 인터페이스

1
2
3
4
public interface State {
    public void select();
}
 
cs

상태 인터페이스 구현한 상태 클래스

1
2
3
4
5
6
7
8
9
10
11
public class AvailableState implements State {
    @Override
    public void select() {
        provideProduct();
    }    
 
    private void provideProduct() {
        ...
    }
}
 
cs

상태 패턴 vs 전략 패턴

사전지식 : 전략패턴

두 패턴 모두 각각의 상황에 따라서 다른 동작을 할때, 각 상황을 별도의 클래스로 다루는 것이 동일하다
상태 패턴의 경우 상태를 클래스로 다루고, 전략 패턴은 전략을 클래스로 다룬다는 것이 동일하다
하지만, 결국 두개가 같은게 아닐까? 라는 의문이 들었고, 찾아본 결과 답은 다음과 같다.

상태 패턴은 상태 객체에서 상태를 바꿀 수 있고, 전략 패턴은 불가능하다

상태 패턴을 먼저 살펴보자. 위의 예제에서 ONELEFT(음료수 하나 남은 상황) 상태에서 자판기에서 음료수를 뽑는다면, 상태가 SOLDOUT으로 바뀌어야한다. (위 코드에서 구체적으로 구현하지는 않았다… 여러분의 이해를 돕기위해서 ㅎㅎ) 이와 같이 상태패턴은 상태 객체에서, 콘텍스트 객체의 상태 변경까지 포함한 개념이다.

전략 패턴을 보자.
별도의 상태를 관리하지 않고, 한번 전략이 선택되면 실행되고 끝이다. 바뀌지 않는다.
예를들면, 고객의 등급에 따라 다른 할인 혜택을 적용할경우

정리하자면,

  • 공통점 : 상태 패턴과 전략 패턴은 각각 상태와 전략을 객체화 해서 관리
  • 차이점 : 상태 패턴은 상태를 관리하고, 전략 패턴은 전략을 관리하지 않음

출처

- https://defacto-standard.tistory.com/47

- https://en.wikipedia.org/wiki/State_pattern

- 개발자가 반드시 정복해야할 객체 지향과 디자인 패턴(최범균 저) Ch.07

+ Recent posts