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 em 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 percorre diferentes estados, em que cada estado determina a cor da luz e como ela faz a transição 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 faz a transição da luz para o 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; em seguida, faz a transição para GreenState
    • GreenState - retorna GREEN como sua cor e imprime Go! Light is green. quando next() é chamado; em seguida, faz a transição para YellowState
    • YellowState - retorna YELLOW como sua cor e imprime Caution! Light is yellow. quando next() é chamado; em seguida, faz a transição para RedState
    Depois, crie uma classe TrafficLight (o contexto) que comece em RedState. Ela deve ter um método setState() para alterar o estado atual, um método getColor() que delega ao estado atual e um método change() que chama next() no estado atual.
  • main.dart: Importe seu arquivo do 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 alteração. Isso mostrará a luz percorrendo todos os estados e retornando ao início.

Observe como a classe TrafficLight não precisa de nenhuma estrutura condicional para determinar o comportamento — cada estado conhece sua própria cor e qual estado vem a seguir. O semáforo simplesmente delega ao estado que está ativo no momento!

Saída esperada:

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

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

Pratique por conta própria: Compilador de Dart online