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á paradoSaída:
Current: Red
Red -> Green
Current: Green
Green -> Yellow
Current: Yellow
Yellow -> Red
Current: Red
Starting music
Already playing
Stopping music
Already stoppedPonto-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.
Desafio
FácilImplemente 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 compress(lamp)edescribe().OffState,LowStateeHighStateos implementam:presschamalamp.set_state(...)com o próximo estado (de desligada para baixa, de baixa para alta, de alta para desligada) edescriberetornaLamp is off,Lamp is on lowouLamp is on high.Lampé o contexto: começa emOffState,set_statetroca o objeto de estado,press_buttondelega ao estado atual estatusretorna 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())
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
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosO Parâmetro selfMétodosAtributosMétodo Construtor (__init__)Recapitulação - Calculadora Simples4Herança
Herança BásicaA Função super()Sobrescrita de MétodoHerança MúltiplaOrdem de Resolução de MétodosRecapitulação - Hierarquia de Funcionários7Métodos Especiais
Introdução aos Métodos MágicosSobrecarga de OperadoresMétodos Mágicos de ContêinerRecapitulação - Lista Personalizada10Padrões de Projeto Parte 1
Introdução a Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão ObserverPadrão Strategy2Decoradores
Introdução aos DecoradoresDecorador de PropriedadeDecorador de Método EstáticoDecorador de Método de Classe5Polimorfismo
Sobrescrita de Método RevisitadaDuck TypingClasses e Métodos AbstratosDesign de InterfacesRecapitulação - Calculadora de Formas8Conceitos Avançados de POO
Composição vs HerançaMixinsMétodos Estáticos e de ClasseDecoradores de ClasseGerenciadores de Contexto11Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão Composite3Propriedades de Classe
Variáveis de Instância vs de ClasseDecoradores de PropriedadeAtributos PrivadosRecapitulação - Gerenciador de Conta Bancária6Encapsulamento
Membros Públicos, Protegidos e PrivadosModificadores de AcessoOcultação de InformaçãoProperty Decorators AvançadosRecapitulação - Sistema de Registro de Alunos12Projeto: Gerenciamento de Biblioteca
Visão Geral do ProjetoClasses Livro e UsuárioSistema de EmpréstimosFuncionalidade de BuscaInterface AdministrativaTestes e IntegraçãoPratique por conta própria: Compilador de Python online