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...)
 
(O estado da porta: classe DoorState)
 
(10 intermediate revisions by the same user not shown)
Line 4: Line 4:
  
 
A uma aplicação de teste que simula alguns estímulos aos quais a porta deve responder.
 
A uma aplicação de teste que simula alguns estímulos aos quais a porta deve responder.
 
+
<source lang="java">
 
   public class StatePattern {
 
   public class StatePattern {
 
     public static void main(String[] args) {
 
     public static void main(String[] args) {
Line 15: Line 15:
 
     }
 
     }
 
   }
 
   }
 +
</source>
  
 
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.
 
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.
Line 24: Line 25:
 
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.
 
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.
  
 +
Note-se que a definição dos objectos dos estados como constantes pode não ser a melhor solução: alguns estados podem ter necessidade de manter informação sobre o decorrer da execução ou podem diferir de outras instâncias da mesma classe no valor dos seus atributos (no caso da porta, isso poderia corresponder, por exemplo, à velocidade de abertura ou fecho da porta).
 +
<source lang="java">
 
   class Door {
 
   class Door {
     public final DoorState CLOSED  = new DoorClosed(this);
+
     private DoorState _state = 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; }
 
     protected void setState(DoorState state) { _state = state; }
 
    
 
    
Line 40: Line 37:
 
     public void status() { System.out.println(_state.status()); }
 
     public void status() { System.out.println(_state.status()); }
 
   }
 
   }
 +
</source>
  
 
=== O estado da porta: classe DoorState ===
 
=== 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.
 
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.
 
+
<source lang="java">
 
   abstract class DoorState {
 
   abstract class DoorState {
 
     protected Door _door;
 
     protected Door _door;
Line 57: Line 55:
 
     public String status() { return getClass().getName(); }
 
     public String status() { return getClass().getName(); }
 
   }
 
   }
 +
</source>
  
 
=== Os vários estados da porta: classes concretas ===
 
=== 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.
 
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.
 
+
<source lang="java">
 
   class DoorOpen extends DoorState {
 
   class DoorOpen extends DoorState {
 
     public DoorOpen(Door door) { super(door); }
 
     public DoorOpen(Door door) { super(door); }
     public void click()  { _door.setState(_door.STAYOPEN); }
+
     public void click()  { _door.setState(new DoorStayOpen(_door)); }
     public void timeout() { _door.setState(_door.CLOSING); }
+
     public void timeout() { _door.setState(new DoorClosing(_door)); }
 
   }
 
   }
  
 
   class DoorOpening extends DoorState {
 
   class DoorOpening extends DoorState {
 
     public DoorOpening(Door door) { super(door); }
 
     public DoorOpening(Door door) { super(door); }
     public void click()    { _door.setState(_door.CLOSING); }
+
     public void click()    { _door.setState(new DoorClosing(_door)); }
     public void complete() { _door.setState(_door.OPEN); }
+
     public void complete() { _door.setState(new DoorOpen(_door)); }
 
   }
 
   }
  
 
   class DoorClosed extends DoorState {
 
   class DoorClosed extends DoorState {
 
     public DoorClosed(Door door) { super(door); }
 
     public DoorClosed(Door door) { super(door); }
     public void click() { _door.setState(_door.OPENING); }
+
     public void click() { _door.setState(new DoorOpening(_door)); }
 
   }
 
   }
  
 
   class DoorClosing extends DoorState {
 
   class DoorClosing extends DoorState {
 
     public DoorClosing(Door door) { super(door); }
 
     public DoorClosing(Door door) { super(door); }
     public void click()    { _porta.setState(_door.OPENING); }
+
     public void click()    { _door.setState(new DoorOpening(_door)); }
     public void complete() { _porta.setState(_door.CLOSED); }
+
     public void complete() { _door.setState(new DoorClosed(_door)); }
 
   }
 
   }
  
 
   class DoorStayOpen extends DoorState {
 
   class DoorStayOpen extends DoorState {
 
     public DoorStayOpen(Door door) { super(door); }
 
     public DoorStayOpen(Door door) { super(door); }
     public void click() { _door.setState(_door.CLOSING); }
+
     public void click() { _door.setState(new DoorClosing(_door)); }
 
   }
 
   }
 +
</source>
  
[[category:OOP]]
+
[[category:Ensino]]
[[category:Teaching]]
+
[[category:PO]]
 +
[[category:PO Exemplos]]
 +
[[category:Java]]

Latest revision as of 18:30, 12 November 2019

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.

Note-se que a definição dos objectos dos estados como constantes pode não ser a melhor solução: alguns estados podem ter necessidade de manter informação sobre o decorrer da execução ou podem diferir de outras instâncias da mesma classe no valor dos seus atributos (no caso da porta, isso poderia corresponder, por exemplo, à velocidade de abertura ou fecho da porta).

  class Door {
    private DoorState _state = new DoorClosed(this);
    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(new DoorStayOpen(_door)); }
    public void timeout() { _door.setState(new DoorClosing(_door)); }
  }

  class DoorOpening extends DoorState {
    public DoorOpening(Door door) { super(door); }
    public void click()    { _door.setState(new DoorClosing(_door)); }
    public void complete() { _door.setState(new DoorOpen(_door)); }
  }

  class DoorClosed extends DoorState {
    public DoorClosed(Door door) { super(door); }
    public void click() { _door.setState(new DoorOpening(_door)); }
  }

  class DoorClosing extends DoorState {
    public DoorClosing(Door door) { super(door); }
    public void click()    { _door.setState(new DoorOpening(_door)); }
    public void complete() { _door.setState(new DoorClosed(_door)); }
  }

  class DoorStayOpen extends DoorState {
    public DoorStayOpen(Door door) { super(door); }
    public void click() { _door.setState(new DoorClosing(_door)); }
  }