Difference between revisions of "State Pattern (padrão de desenho)/Porta Automática"

From Wiki**3

< State Pattern (padrão de desenho)
(New page: A porta automática pode estar en vários estados que determinam a sua resposta a estímulos. Os vários estados são "Closed" (porta fechada); "Closing" (porta a fechar); "StayOpen" (perm...)
 
Line 92: Line 92:
 
[[category:OOP]]
 
[[category:OOP]]
 
[[category:Teaching]]
 
[[category:Teaching]]
 +
[[category:PO Exemplos]]

Revision as of 18:46, 14 October 2013

A porta automática pode estar en vários estados que determinam a sua resposta a estímulos. Os vários estados são "Closed" (porta fechada); "Closing" (porta a fechar); "StayOpen" (permanentemente aberta); "Open" (aberta); "Opening" (porta a abrir). Os estímulos são "click" (botão de abrir/fechar premido); "complete" (fim do ciclo de abertura/fecho); "timeout" (passagem de tempo num dado estado).

State-dp-state-diagram-door.png

A uma aplicação de teste que simula alguns estímulos aos quais a porta deve responder.

 public class StatePattern {
   public static void main(String[] args) {
     Door door = new Door();   // Closed
     door.click();
     door.complete();
     door.timeout();
     door.click();
     door.status();
   }
 }

Se não se utilizasse o padrão State, fazendo com que sejam os objectos do estado a responder aos estímulos, o controlo da máquina de estados teria de ser implementado directamente na porta fazendo com que houvesse mais código a manter e dificultando a gestão dos estados de forma independente, especialmente, mas sem limitação, no que respeita à definição de novos estados e comportamentos a eles associados.

As classes seguintes ilustram os intervenientes neste padrão.

Porta: classe Door

Esta classe representa a porta nas condições descritas acima. Note-se a definição das respostas aos estímulos em função do estado.

 class Door {
   public final DoorState CLOSED   = new DoorClosed(this);
   public final DoorState OPENING  = new DoorOpening(this);
   public final DoorState OPEN     = new DoorOpen(this);
   public final DoorState CLOSING  = new DoorClosing(this);
   public final DoorState STAYOPEN = new DoorStayOpen(this);
 
   private DoorState _state = CLOSED;
   protected void setState(DoorState state) { _state = state; }
 
   public void click()    { _state.click();    }
   public void complete() { _state.complete(); }
   public void timeout()  { _state.timeout();  }
 
   public void status() { System.out.println(_state.status()); }
 }

O estado da porta: classe DoorState

Esta classe representa a abstracção do estado da porta. Os estados concretos vão aumentar a funcionalidade desta classe, de acordo com o comportamento desejado.

 abstract class DoorState {
   protected Door _door;

   public DoorState(Door door) { _door = door; }

   public abstract void click();

   public void timeout()  { }
   public void complete() { }

   public String status() { return getClass().getName(); }
 }

Os vários estados da porta: classes concretas

Cada uma das classes implementa o estado correspondente a uma dada situação da porta. É nestas classes que a resposta aos estímulos é realmente definida.

 class DoorOpen extends DoorState {
   public DoorOpen(Door door) { super(door); }
   public void click()   { _door.setState(_door.STAYOPEN); }
   public void timeout() { _door.setState(_door.CLOSING); }
 }
 class DoorOpening extends DoorState {
   public DoorOpening(Door door) { super(door); }
   public void click()    { _door.setState(_door.CLOSING); }
   public void complete() { _door.setState(_door.OPEN); }
 }
 class DoorClosed extends DoorState {
   public DoorClosed(Door door) { super(door); }
   public void click() { _door.setState(_door.OPENING); }
 }
 class DoorClosing extends DoorState {
   public DoorClosing(Door door) { super(door); }
   public void click()    { _porta.setState(_door.OPENING); }
   public void complete() { _porta.setState(_door.CLOSED); }
 }
 class DoorStayOpen extends DoorState {
   public DoorStayOpen(Door door) { super(door); }
   public void click() { _door.setState(_door.CLOSING); }
 }