Menu
Coddy logo textTech

상태 패턴

Coddy Python 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 64개 중 53번째.

State Pattern을 사용하면 객체는 내부 상태가 변경될 때 동작을 변경할 수 있습니다. 객체는 현재 상태에 따라 클래스가 변경되는 것처럼 보입니다.

신호등을 위한 간단한 상태 클래스는 다음과 같습니다:

class RedState:
    def next_state(self, light):
        print("Red -> Green")
        light.state = GreenState()
    
    def current_color(self):
        return "Red"

class GreenState:
    def next_state(self, light):
        print("Green -> Yellow")
        light.state = YellowState()
    
    def current_color(self):
        return "Green"

class YellowState:
    def next_state(self, light):
        print("Yellow -> Red")
        light.state = RedState()
    
    def current_color(self):
        return "Yellow"

각 상태는 다음 상태로 전환할 때 발생하는 동작을 정의합니다.

현재 상태를 보유하는 컨텍스트 클래스를 만드세요:

class TrafficLight:
    def __init__(self):
        self.state = RedState()  # 빨간색으로 시작
    
    def change(self):
        self.state.next_state(self)
    
    def get_color(self):
        return self.state.current_color()

신호등은 현재 상태 객체에 동작을 위임합니다.

신호등을 사용하세요:

light = TrafficLight()
print(f"Current: {light.get_color()}")

light.change()  # 빨간색 -> 초록색
print(f"Current: {light.get_color()}")

light.change()  # 초록색 -> 노란색
print(f"Current: {light.get_color()}")

light.change()  # 노란색 -> 빨간색
print(f"Current: {light.get_color()}")

간단한 플레이어로 또 다른 예제를 만들어 보세요:

class PlayingState:
    def play(self, player):
        print("Already playing")
    
    def stop(self, player):
        print("Stopping music")
        player.state = StoppedState()

class StoppedState:
    def play(self, player):
        print("Starting music")
        player.state = PlayingState()
    
    def stop(self, player):
        print("Already stopped")

class MusicPlayer:
    def __init__(self):
        self.state = StoppedState()
    
    def play(self):
        self.state.play(self)
    
    def stop(self):
        self.state.stop(self)

player = MusicPlayer()
player.play()   # 음악 시작
player.play()   # 이미 재생 중
player.stop()   # 음악 중지
player.stop()   # 이미 중지됨

출력:

Current: Red
Red -> Green
Current: Green
Green -> Yellow
Current: Yellow
Yellow -> Red
Current: Red
Starting music
Already playing
Stopping music
Already stopped

핵심 요점: 상태 패턴은 상태별 동작을 별도의 클래스에 캡슐화하고 컨텍스트 객체가 현재 상태에 위임하도록 합니다. 상태가 변경되면 동작도 자동으로 변경됩니다. 이를 통해 복잡한 if/else 문을 없애고 새로운 상태를 더 쉽게 추가할 수 있습니다.

challenge icon

챌린지

쉬움

버튼 하나가 있는 램프에 대한 State 패턴을 state.py에 구현하세요. 버튼을 누를 때마다 램프는 세 가지 상태를 순환합니다: 꺼짐, 약한 밝기, 강한 밝기, 그리고 다시 꺼짐으로 돌아갑니다. 문자열에 대한 if 체인을 사용하는 대신, 각 상태는 버튼을 눌렀을 때 어떤 일이 일어나는지 알고 있는 고유한 객체입니다.

  • LampStatepress(lamp)describe()를 포함하는 기본 클래스입니다.
  • OffState, LowState, HighState는 이를 구현합니다. press는 다음 상태를 인수로 하여 lamp.set_state(...)를 호출하고(꺼짐에서 약한 밝기, 약한 밝기에서 강한 밝기, 강한 밝기에서 꺼짐), describeLamp is off, Lamp is on low 또는 Lamp is on high를 반환합니다.
  • Lamp는 컨텍스트입니다. OffState에서 시작하고, set_state는 상태 객체를 교체하며, press_button은 현재 상태에 처리를 위임하고, status는 현재 설명을 반환합니다.

driver.py는 잠겨 있습니다. 이 파일은 버튼을 누르고 상태를 출력합니다. Lamp는 현재 어떤 상태인지 전혀 확인하지 않으며, 상태 객체가 이를 결정한다는 점에 주목하세요.

직접 해보기

from state import Lamp

# 테스트 케이스 핸들러 (변경하지 마세요)
test_case = input()
lamp = Lamp()

if test_case == "initial_test":
    print(lamp.status())
elif test_case == "one_press_test":
    lamp.press_button()
    print(lamp.status())
elif test_case == "cycle_test":
    for _ in range(4):
        print(lamp.status())
        lamp.press_button()
elif test_case == "many_presses_test":
    for _ in range(7):
        lamp.press_button()
    print(lamp.status())
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: 온라인 Python 컴파일러