Menu
Coddy logo textTech

Padrão State

Parte da seção Programação Orientada a Objetos do Journey de Python da Coddy. Lição 53 de 64.

O padrão State permite que um objeto mude seu comportamento quando seu estado interno muda. O objeto parece mudar de classe com base em seu estado atual.

Aqui estão classes de estado simples para um semáforo:

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"

Cada estado define o que acontece ao fazer a transição para o próximo estado.

Crie uma classe de contexto que mantenha o estado atual:

class TrafficLight:
    def __init__(self):
        self.state = RedState()  # Inicia com vermelho
    
    def change(self):
        self.state.next_state(self)
    
    def get_color(self):
        return self.state.current_color()

O semáforo delega o comportamento ao seu objeto de estado atual.

Use o semáforo:

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

light.change()  # Vermelho -> Verde
print(f"Current: {light.get_color()}")

light.change()  # Verde -> Amarelo
print(f"Current: {light.get_color()}")

light.change()  # Amarelo -> Vermelho
print(f"Current: {light.get_color()}")

Crie outro exemplo com um player simples:

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()   # Iniciando a música
player.play()   # Já está tocando
player.stop()   # Parando a música
player.stop()   # Já está parado

Saída:

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

Ponto-chave: o Padrão State encapsula o comportamento específico de cada estado em classes separadas e permite que o objeto de contexto delegue ao estado atual. Quando o estado muda, o comportamento muda automaticamente. Isso elimina instruções complexas de if/else e facilita a adição de novos estados.

challenge icon

Desafio

Fácil

Implemente o padrão State em state.py para uma lâmpada com um botão. Cada pressionamento faz a lâmpada passar por três estados em um ciclo: desligada, baixa, alta e voltar a desligada. Em vez de uma cadeia de if baseada em uma string, cada estado é seu próprio objeto, que sabe o que acontece quando o botão é pressionado.

  • LampState é a classe base com press(lamp) e describe().
  • OffState, LowState e HighState os implementam: press chama lamp.set_state(...) com o próximo estado (de desligada para baixa, de baixa para alta, de alta para desligada) e describe retorna Lamp is off, Lamp is on low ou Lamp is on high.
  • Lamp é o contexto: começa em OffState, set_state troca o objeto de estado, press_button delega ao estado atual e status retorna a descrição atual.

driver.py está bloqueado: ele pressiona o botão e imprime o status. Observe que Lamp nunca verifica em qual estado está; os objetos de estado decidem.

Experimente você mesmo

from state import Lamp

# Manipulador de casos de teste (não altere)
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 iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação Orientada a Objetos

Pratique por conta própria: Compilador de Python online