
스테이트 패턴(State Pattern)은 객체의 내부 상태가 변경될 때 객체의 행동(메서드)을 변경할 수 있도록 하는 행동 디자인 패턴 중 하나입니다. 스테이트 패턴은 주로 객체의 상태가 다양하고 상태에 따라 객체의 행동이 달라져야 할 때 사용됩니다. 이 패턴을 사용하면 상태 관련 코드를 객체 내부로 캡슐화하고, 객체의 행동을 상태 객체로 위임하여 코드의 유지보수성을 향상시킵니다.
InefficientTrafficLight.java
public class InefficientTrafficLight {
public static final int RED = 0;
public static final int GREEN = 1;
public static final int YELLOW = 2;
private int currentState = RED;
public void change() {
if (currentState == RED) {
System.out.println("빨간 불 - 정지");
// 빨간 불 상태에서의 동작을 수행
// 예를 들어, 일정 시간 기다린 후 다음 상태로 전환할 수 있음
currentState = GREEN;
} else if (currentState == GREEN) {
System.out.println("초록 불 - 진행");
// 초록 불 상태에서의 동작을 수행
// 예를 들어, 일정 시간 기다린 후 다음 상태로 전환할 수 있음
currentState = YELLOW;
} else if (currentState == YELLOW) {
System.out.println("노란 불 - 경고");
// 노란 불 상태에서의 동작을 수행
// 예를 들어, 일정 시간 기다린 후 다음 상태로 전환할 수 있음
currentState = RED;
}
}
public static void main(String[] args) {
InefficientTrafficLight trafficLight = new InefficientTrafficLight();
// 상태 변경을 여러 번 반복하여 신호등 동작 시뮬레이션
for (int i = 0; i < 5; i++) {
trafficLight.change();
}
}
}
Main.java
/**
* 이 클래스는 주문을 처리하는 데 사용되는 식당 객체를 나타냅니다.
*/
public class MainWithoutProxy {
/**
* 주문 처리를 위한 메인 메소드입니다.
*/
public static void main(String[] args) {
// 식당 객체 생성
RestaurantWithoutProxy restaurant = new RestaurantWithoutProxy();
// 고객의 이름 설정
restaurant.setCustomerName("Jinny");
System.out.println("현재 주문자 이름: " + restaurant.getCustomerName());
// 주문 처리
restaurant.placeOrder("피자");
}
}
위에 코드는 State 패턴을 적용하지 않은 프로그램입니다. 이 프로그램의 관련 문서인 Javadoc을 보시고 싶다면 StateBefore
(단, 해당 문서는 StateBefore/docs 폴더에 있습니다.)을 눌러주세요.
이 프로그램은 아래와 같이 여러가지 비효율적인 부분들이 있습니다.
스테이트 패턴 적용 전:
if문을 사용하여 상태를 관리하고, 각 상태에 따른 동작을 수행하는 코드가 길고 복잡해집니다.이러한 단점들을 해결하기 위해 State 패턴을 활용해 코드를 수정해보았습니다.
이러한 비효율성과 단점을 해결하기 위해 상태 패턴을 사용면, 아래와 같이 효율적인 코드를 작성할 수 있습니다.
TrafficLightState.java
// 상태 패턴에서 사용할 상태 인터페이스
public interface TrafficLightState {
void handle(TrafficLightContext context);
}
TrafficLightContext.java
// 신호등 컨텍스트 클래스
public class TrafficLightContext {
private TrafficLightState state;
public TrafficLightContext() {
// 초기 상태를 빨간 불로 설정
state = new RedLightState();
}
public void setState(TrafficLightState state) {
this.state = state;
}
public void change() {
// 상태 변경 메소드
state.handle(this);
}
}
RedLightState.java
// 빨간 불 상태 클래스
public class RedLightState implements TrafficLightState {
@Override
public void handle(TrafficLightContext context) {
System.out.println("빨간 불 - 정지");
// 빨간 불 상태에서의 동작을 수행
// 예를 들어, 일정 시간 기다린 후 다음 상태로 전환할 수 있음
context.setState(new GreenLightState());
}
}
YellowLightState.java
// 노란 불 상태 클래스
public class YellowLightState implements TrafficLightState {
@Override
public void handle(TrafficLightContext context) {
System.out.println("노란 불 - 경고");
// 노란 불 상태에서의 동작을 수행
// 예를 들어, 일정 시간 기다린 후 다음 상태로 전환할 수 있음
context.setState(new RedLightState());
}
}
GreenLightState.java
// 초록 불 상태 클래스
public class GreenLightState implements TrafficLightState {
@Override
public void handle(TrafficLightContext context) {
System.out.println("초록 불 - 진행");
// 초록 불 상태에서의 동작을 수행
// 예를 들어, 일정 시간 기다린 후 다음 상태로 전환할 수 있음
context.setState(new YellowLightState());
}
}
Main.java
public class Main {
public static void main(String[] args) {
TrafficLightContext trafficLight = new TrafficLightContext();
// 상태 변경을 여러 번 반복하여 신호등 동작 시뮬레이션
for (int i = 0; i < 5; i++) {
trafficLight.change();
}
}
}
스테이트 패턴 적용 후:
RedLightState, GreenLightState, YellowLightState 와 같은 구체적인 클래스를 생성할 수 있습니다. 이렇게 하면 새로운 상태를 추가하거나 기존 상태를 변경하기가 쉽습니다.RedLightState 클래스는 "빨간 불 - 정지" 동작을 포함하고, 이로 인해 코드의 가독성이 향상됩니다.RedLightState 클래스에서 다음 상태로 전환하는 로직이 있습니다. 이로써 상태 전환 관련 코드가 한 곳에 집중되어 관리와 디버깅이 용이합니다.
위 사진은 State Pattern을 사용해서 신호등을 구현한 프로그램의 UML입니다.클래스 및 인터페이스와 관련된 설명은 아래와 같습니다.
TrafficLight 클래스는 상태 패턴의 컨텍스트 역할을 합니다. 이 클래스는 현재 상태를 관리하고, 상태에 따라 동작을 수행합니다. state 필드는 현재 상태를 저장하며, setState() 메소드를 통해 상태를 변경하고, change() 메소드는 상태에 따른 동작을 수행합니다.TrafficLightState 인터페이스는 모든 상태 클래스가 구현해야 하는 인터페이스입니다. handle() 메소드는 각 상태에서 수행할 동작을 정의합니다.TrafficLightState 인터페이스를 구현합니다. 각 상태 클래스는 handle() 메소드에서 해당 상태에서의 동작을 정의합니다. 예를 들어, RedLightState에서는 "빨간 불 - 정지" 동작을, GreenLightState에서는 "초록 불 - 진행" 동작을 정의합니다.상태 패턴을 표현하고 있는 이 구조에서는, 컨텍스트 객체가 현재 상태를 관리하고, 각 상태 객체가 해당 상태에서의 동작을 구현함을 보여주고 있습니다. 상태 패턴은 객체의 상태에 따른 동작을 캡슐화하여 코드를 유지 보수하고 확장하기 쉽게 만들 수 있습니다.
JavaDoc1
JavaDoc2
index.html
javadoc 파일은 StateAfter/docs 폴더에도 있습니다.
State Pattern을 활용해 상태 관련 로직을 캡슐화함으로써 유지보수와 확장이 더 쉬워지게 만들어봤습니다.
또한 조건문을 최소화하여 코드의 가독성을 향상시켜보니 이 패턴의 장점을 느낄 수 있었습니다.
이 패턴을 활용해 신호등 프로그램을 짜보니 새로운 상태를 추가하거나 기존 상태를 수정하기 쉬운 것 같고 효율적인 것 같습니다.