Difference between revisions of "State Pattern (padrão de desenho)/Exercício 01: Semáforo"

From Wiki**3

< State Pattern (padrão de desenho)
(Classe TrafficLight (externa) e TrafficLight.State (interna))
Line 14: Line 14:
 
Notar ainda que não é estritamente necessário que a superclasse das classes dos estados seja interna à classe detentora do estado ('''TrafficLight'''). Optou-se por definir a classe como interna para demonstrar como a classe interna pode aceder a estado privado da folha.
 
Notar ainda que não é estritamente necessário que a superclasse das classes dos estados seja interna à classe detentora do estado ('''TrafficLight'''). Optou-se por definir a classe como interna para demonstrar como a classe interna pode aceder a estado privado da folha.
  
== Classe TrafficLight (externa) e TrafficLight.State (interna) ==
+
{{CollapsedCode|Ficheiro '''TrafficLight.java''' (classe TrafficLight (externa) e TrafficLight.State (interna))|
 
 
 
<java5>
 
<java5>
 
public class TrafficLight {
 
public class TrafficLight {
Line 105: Line 104:
 
}
 
}
 
</java5>
 
</java5>
 +
}}
  
== Classe Ticking ==
 
  
 
Abstract class for representing normal behavior. See also the next section (color classes).
 
Abstract class for representing normal behavior. See also the next section (color classes).
Line 112: Line 111:
 
Ticking states are those corresponding to the usual three colors.
 
Ticking states are those corresponding to the usual three colors.
  
 +
{{CollapsedCode|Ficheiro '''Ticking.java'''|
 
<java5>
 
<java5>
 
public abstract class Ticking extends TrafficLight.State {
 
public abstract class Ticking extends TrafficLight.State {
Line 143: Line 143:
 
}
 
}
 
</java5>
 
</java5>
 
+
}}
== Classes Red, Yellow, Green ==
 
  
 
Red light.
 
Red light.
  
 +
{{CollapsedCode|Ficheiro '''Red.java'''|
 
<java5>
 
<java5>
 
public class Red extends Ticking {
 
public class Red extends Ticking {
Line 175: Line 175:
 
}
 
}
 
</java5>
 
</java5>
 +
}}
  
 
Yellow light.
 
Yellow light.
  
 +
{{CollapsedCode|Ficheiro '''Yellow.java'''|
 
<java5>
 
<java5>
 
public class Yellow extends Ticking {
 
public class Yellow extends Ticking {
Line 205: Line 207:
 
}
 
}
 
</java5>
 
</java5>
 +
}}
  
 
Green light.
 
Green light.
  
 +
{{ColllapsedCode|Ficheiro '''Green.java'''|
 
<java5>
 
<java5>
 
public class Green extends Ticking {
 
public class Green extends Ticking {
Line 235: Line 239:
 
}
 
}
 
</java5>
 
</java5>
 
+
}}
== Classe Panic ==
 
  
 
Panic state.
 
Panic state.
  
 +
{{CollapsedCode|Ficheiro '''Panic.java'''|
 
<java5>
 
<java5>
 
public class Panic extends TrafficLight.State {
 
public class Panic extends TrafficLight.State {
Line 293: Line 297:
 
}
 
}
 
</java5>
 
</java5>
 
+
}}
== Classe Blinking ==
 
  
 
Blinking light (off).
 
Blinking light (off).
  
 +
{{CollapsedCode|Ficheiro '''Blinking.java'''|
 
<java5>
 
<java5>
 
public class Blinking extends TrafficLight.State {
 
public class Blinking extends TrafficLight.State {
Line 351: Line 355:
 
}
 
}
 
</java5>
 
</java5>
 
+
}}
== Classe App ==
 
  
 
Simple application to illustrate the traffic light's state changes.
 
Simple application to illustrate the traffic light's state changes.
  
 +
{{CollapsedCode|Ficheiro '''App.java'''|
 
<java5>
 
<java5>
 
public class App {
 
public class App {
Line 378: Line 382:
 
}
 
}
 
</java5>
 
</java5>
 +
}}
  
 
= Compiling and Running =
 
= Compiling and Running =

Revision as of 16:04, 1 September 2015

Problema

Um semáforo tem um temporizador que emite impulsos a intervalos regulares. Estes impulsos chegam ao controlador do semáforo sob a forma de chamadas ao método tick. Em funcionamento normal, um tick faz com que o semáforo passe da cor vermelha para a verde, da verde para a amarela e da amarela para a vermelha, reiniciando o ciclo. O semáforo tem ainda vários botões para controlo de situações especiais. Assim, o botão de pânico que faz com que o controlador mude o semáforo para a cor vermelha, qualquer que seja a anterior (método panic). O botão off faz com que o semáforo mude imediatamente para amarelo intermitente (método off). Esta situação é interrompida através dos botões on (volta ao comportamento normal; método on) ou de pânico. O botão on é a única forma de fazer semáforo sair da situação de pânico e recuperar o funcionamento normal. Além do código de controlo, o semáforo tem ainda um método (status) que permite saber a cor actual do semáforo. O semáforo começa intermitente e quando recupera das situações de intermitência e de pânico fica vermelho.

Implemente o semáforo e a sua máquina de estados.

Solução

A solução apresentada considera que a superclasse dos estados é interna (tem, desse modo, acesso ao estado interno do semáforo e não é necessário exportar nenhuma interface para gestão de estados.

Notar os aspectos de herança de classes internas e a forma especial de chamada ao contrutor da superclasse interna. Notar ainda como uma classe interna (State) pode aceder ao objecto actual da classe externa (TrafficLight.this).

Notar ainda que não é estritamente necessário que a superclasse das classes dos estados seja interna à classe detentora do estado (TrafficLight). Optou-se por definir a classe como interna para demonstrar como a classe interna pode aceder a estado privado da folha.

Ficheiro TrafficLight.java (classe TrafficLight (externa) e TrafficLight.State (interna))
{{{2}}}


Abstract class for representing normal behavior. See also the next section (color classes).

Ticking states are those corresponding to the usual three colors.

Ficheiro Ticking.java

<java5> public abstract class Ticking extends TrafficLight.State {

/** * @param light */ Ticking(TrafficLight light) { light.super(); }

/** * All colors switch to blinking when "off" is pressed. * * @see TrafficLight.State#off() */ @Override public void off() { setState(new Blinking(getLight())); }

/** * All colors switch to panic when the button is pressed. * * @see TrafficLight.State#panic() */ @Override public void panic() { setState(new Panic(getLight())); } } </java5>

Red light.

Ficheiro Red.java

<java5> public class Red extends Ticking {

/** * @param light */ Red(TrafficLight light) { super(light); }

/** * @see TrafficLight.State#tick() */ @Override public void tick() { setState(new Green(getLight())); }

/** * @see TrafficLight.State#status() */ @Override public String status() { return "Red"; } } </java5>

Yellow light.

Ficheiro Yellow.java

<java5> public class Yellow extends Ticking {

/** * @param light */ Yellow(TrafficLight light) { super(light); }

/** * @see TrafficLight.State#tick() */ @Override public void tick() { setState(new Red(getLight())); }

/** * @see TrafficLight.State#status() */ @Override public String status() { return "Yellow"; } } </java5>

Green light.

Template:ColllapsedCode

Panic state.

Ficheiro Panic.java

<java5> public class Panic extends TrafficLight.State {

/** * @param light */ Panic(TrafficLight light) { light.super(); }

/** * Return to "ticking" (normal) mode. * * @see TrafficLight.State#on() */ @Override public void on() { setState(new Red(getLight())); }

/** * @see TrafficLight.State#off() */ @Override public void off() { // do nothing: already off }

/** * @see TrafficLight.State#panic() */ @Override public void panic() { // do nothing: already in panic mode }

/** * @see TrafficLight.State#tick() */ @Override public void tick() { // do nothing: ignore ticks in panic mode }

/** * @see TrafficLight.State#status() */ @Override public String status() { return "Panic"; } } </java5>

Blinking light (off).

Ficheiro Blinking.java

<java5> public class Blinking extends TrafficLight.State {

/** * @param light */ Blinking(TrafficLight light) { light.super(); }

/** * Return to "ticking" (normal) mode. * * @see TrafficLight.State#on() */ @Override public void on() { setState(new Red(getLight())); }

/** * @see TrafficLight.State#off() */ @Override public void off() { // do nothing: already off }

/** * @see TrafficLight.State#panic() */ @Override public void panic() { setState(new Panic(getLight())); }

/** * @see TrafficLight.State#tick() */ @Override public void tick() { // do nothing: ignore ticks }

/** * @see TrafficLight.State#status() */ @Override public String status() { return "Blinking"; } } </java5>

Simple application to illustrate the traffic light's state changes.

Ficheiro App.java
{{{2}}}

Compiling and Running

Compiling

Running

java App

Result:

Light status: Blinking
[Blinking] --(off)-> [Blinking]
[Blinking] --(panic)-> [Panic]
[Panic] --(on)-> [Red]
[Red] --(tick)-> [Green]
[Green] --(tick)-> [Yellow]
[Yellow] --(tick)-> [Red]
[Red] --(tick)-> [Green]
[Green] --(panic)-> [Panic]
[Panic] --(off)-> [Panic]
[Panic] --(on)-> [Red]
[Red] --(off)-> [Blinking]