Padrão State
Parte da seção Object Oriented Programming do Journey de Python da Coddy — lição 53 de 64.
O Padrão State permite que um objeto altere seu comportamento quando seu estado interno muda. O objeto parece mudar sua 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 transitar para o próximo estado.
Crie uma classe de contexto que mantém o estado atual:
class TrafficLight:
def __init__(self):
self.state = RedState() # Comece 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 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 do estado em classes separadas e permite que o objeto de contexto delegue para o estado atual. Quando o estado muda, o comportamento muda automaticamente. Isso elimina declarações if/else complexas e torna a adição de novos estados mais fácil.
Desafio
FácilNeste desafio, você implementará a classe State em state.py com encapsulamento e métodos adequados. O arquivo contém comentários TODO detalhados para orientar sua implementação passo a passo.
A suíte de testes foi projetada para verificar se sua implementação atende a todos os requisitos e lida corretamente com condições excepcionais. Use os resultados dos testes para entender o comportamento esperado e refinar sua solução.
Folha de consulta
O Padrão State permite que um objeto altere seu comportamento quando seu estado interno muda. O objeto parece mudar sua classe com base em seu estado atual.
Crie classes de estado que definam o comportamento para cada estado:
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"Crie uma classe de contexto que mantenha o estado atual:
class TrafficLight:
def __init__(self):
self.state = RedState() # Começa com vermelho
def change(self):
self.state.next_state(self)
def get_color(self):
return self.state.current_color()Exemplo de uso:
light = TrafficLight()
print(f"Current: {light.get_color()}") # Atual: Red
light.change() # Red -> Green
print(f"Current: {light.get_color()}") # Atual: GreenO Padrão State encapsula o comportamento específico do estado em classes separadas e permite que o objeto de contexto delegue para o estado atual. Isso elimina declarações if/else complexas e facilita a adição de novos estados.
Experimente você mesmo
from state import State
# Manipulador abrangente de casos de teste
test_case = input()
if test_case == "basic_test":
obj = State("Test Name")
obj.display_info()
elif test_case == "validation_test":
obj = State("Validation Test")
print(f"Name: {obj.name}")
elif test_case == "empty_name_test":
obj = State("")
obj.display_info()
print(f"Name property: {obj.name}")
elif test_case == "special_chars_test":
obj = State("Test@#$%")
obj.display_info()
print(f"Name property: {obj.name}")
elif test_case == "long_name_test":
long_name = "A" * 100
obj = State(long_name)
obj.display_info()
print(f"Name length: {len(obj.name)}")
elif test_case == "multiple_states_test":
states = [
State("California"),
State("Texas"),
State("New York"),
State("Florida")
]
for state in states:
state.display_info()
print(f"Name via property: {state.name}")
elif test_case == "attribute_access_test":
obj = State("Access Test")
# Acesso direto ao atributo privado (não recomendado)
print(f"Direct access (not recommended): {obj._name}")
# Acesso via propriedade (recomendado)
print(f"Property access (recommended): {obj.name}")
elif test_case == "property_behavior_test":
obj = State("Original Name")
print(f"Original name: {obj.name}")
# Tenta modificar o nome (falhará pois não há um setter)
try:
obj.name = "New Name"
except AttributeError as e:
print(f"Error when trying to modify name: {e}")
# Mostra que o nome permanece inalterado
print(f"Name after modification attempt: {obj.name}")Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Object Oriented Programming
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ário