Menu
Coddy logo textTech

Padrão State

Parte da seção Programação Orientada a Objetos do Journey de Dart da Coddy — lição 98 de 110.

O padrão State permite que um objeto altere seu comportamento quando seu estado interno muda, fazendo com que pareça que o objeto mudou de classe. Em vez de usar condicionais complexas para lidar com diferentes estados, você encapsula cada estado em sua própria classe e delega o comportamento ao objeto de estado atual.

O padrão consiste em um Context que mantém uma referência ao estado atual, e classes State que definem o comportamento para cada estado possível. Quando o estado do contexto muda, seu comportamento muda automaticamente:

abstract class DocumentState {
  void publish(Document doc);
  String getStatus();
}

class DraftState implements DocumentState {
  @override
  void publish(Document doc) {
    print('Moving to review...');
    doc.setState(ReviewState());
  }

  @override
  String getStatus() => 'Draft';
}

class ReviewState implements DocumentState {
  @override
  void publish(Document doc) {
    print('Document published!');
    doc.setState(PublishedState());
  }

  @override
  String getStatus() => 'Under Review';
}

class PublishedState implements DocumentState {
  @override
  void publish(Document doc) {
    print('Already published.');
  }

  @override
  String getStatus() => 'Published';
}

class Document {
  DocumentState _state = DraftState();

  void setState(DocumentState state) => _state = state;
  void publish() => _state.publish(this);
  String getStatus() => _state.getStatus();
}

void main() {
  var doc = Document();
  print(doc.getStatus());  // Rascunho
  doc.publish();           // Movendo para revisão...
  print(doc.getStatus());  // Em revisão
  doc.publish();           // Documento publicado!
  print(doc.getStatus());  // Publicado
}

Cada classe de estado trata a ação publish() de forma diferente e pode transicionar o documento para o próximo estado. A classe Document não precisa de condicionais para verificar seu estado atual — ela simplesmente delega para qualquer objeto de estado que esteja ativo no momento. Este padrão é ideal para objetos com modos de comportamento distintos, como processamento de pedidos, players de mídia ou sistemas de fluxo de trabalho.

challenge icon

Desafio

Fácil

Vamos construir um sistema de semáforo usando o padrão State! Você criará um semáforo que alterna entre diferentes estados, onde cada estado determina a cor da luz e como ela transita para o próximo estado.

Você organizará seu código em dois arquivos:

  • traffic_light.dart: Este arquivo contém suas classes de estado e o contexto do semáforo. Crie uma classe abstrata TrafficLightState com dois métodos: String getColor() que retorna a cor atual da luz, e void next(TrafficLight light) que transita a luz para o seu próximo estado. Implemente três classes de estado concretas:
    • RedState - retorna RED como sua cor e imprime Stop! Light is red. quando next() é chamado, então transita para GreenState
    • GreenState - retorna GREEN como sua cor e imprime Go! Light is green. quando next() é chamado, então transita para YellowState
    • YellowState - retorna YELLOW como sua cor e imprime Caution! Light is yellow. quando next() é chamado, então transita para RedState
    Em seguida, crie uma classe TrafficLight (o contexto) que começa em RedState. Ela deve ter um método setState() para alterar o estado atual, um método getColor() que delega para o estado atual, e um método change() que chama next() no estado atual.
  • main.dart: Importe seu arquivo de semáforo e demonstre o padrão State em ação. Crie um TrafficLight e imprima sua cor inicial. Em seguida, chame change() três vezes, imprimindo a cor após cada mudança. Isso mostrará o semáforo alternando por todos os estados e voltando ao início.

Observe como a classe TrafficLight não precisa de condicionais para determinar o comportamento - cada estado conhece sua própria cor e qual estado vem a seguir. O semáforo simplesmente delega para qualquer estado que esteja ativo no momento!

Saída esperada:

RED
Stop! Light is red.
GREEN
Go! Light is green.
YELLOW
Caution! Light is yellow.
RED

Folha de consulta

O padrão State permite que um objeto altere seu comportamento quando seu estado interno muda. Em vez de usar condicionais complexas, cada estado é encapsulado em sua própria classe.

O padrão consiste em:

  • Context: Mantém uma referência ao estado atual
  • State classes: Definem o comportamento para cada estado possível

Estrutura básica:

abstract class DocumentState {
  void publish(Document doc);
  String getStatus();
}

class DraftState implements DocumentState {
  @override
  void publish(Document doc) {
    print('Moving to review...');
    doc.setState(ReviewState());
  }

  @override
  String getStatus() => 'Draft';
}

class Document {
  DocumentState _state = DraftState();

  void setState(DocumentState state) => _state = state;
  void publish() => _state.publish(this);
  String getStatus() => _state.getStatus();
}

O contexto delega o comportamento ao objeto de estado atual. Cada classe de estado lida com as ações de forma diferente e pode transitar para o próximo estado. Isso elimina a necessidade de condicionais para verificar o estado atual.

Ideal para objetos com modos de comportamento distintos, como processamento de pedidos, players de mídia ou sistemas de fluxo de trabalho.

Experimente você mesmo

import 'traffic_light.dart';

void main() {
  // TODO: Criar uma instância de TrafficLight
  
  // TODO: Imprimir a cor inicial
  
  // TODO: Chamar change() e imprimir a cor (3 vezes para percorrer todos os estados)
  // Primeira mudança: RED -> GREEN
  
  // Segunda mudança: GREEN -> YELLOW
  
  // Terceira mudança: YELLOW -> RED
}
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