Máquina de Lavar
Uma máquina de lavar tem um mecanismo que gere a abertura da porta, por forma a evitar acidentes com crianças. A máquina tem os seguintes botões e sensores: botão “ligar/desligar” (chama o método power); botão “abrir porta” (método open); sensor “porta fechada” (método closed). A máquina tem ainda um temporizador que emite um impulsos a cada segundo (por cada impulso é chamado o método tick). A máquina apenas pode ser ligada (botão “ligar/desligar”) se a porta estiver fechada: a máquina arranca e apenas pára quando o número de impulsos for igual a 5400 ou quando o botão “ligar/desligar” for premido, interrompendo a lavagem. Quer num caso, quer noutro, a máquina não permite abertura imediata da porta: é necessário esperar 120 impulsos para que a máquina reaja ao botão “abrir porta” (durante o tempo de espera, o botão “ligar/desligar” é ignorado). Caso a porta tenha sido fechada, mas não se tenha iniciado a lavagem, a abertura da porta é imediata. A máquina está inicialmente desligada e a porta está aberta. Represente a abertura da porta através da impressão de uma cadeia de caracteres.
Implemente todas as classes da máquina de lavar com controlador de segurança.
Solução
Usa-se o padrão State para controlo da porta da máquina.
A máquina é simples: contém as funções a desempenhar e que dependem do estado. Foram omitidos aspectos não importantes para o problema (i.e., como se fecha a porta e como se produzem os impulsos).
[Expand] class WashingMachine
|
public class WashingMachine {
/** Machine state. */
private State _mode = new Open(this);
/** closed sensor */
public void closed() { _mode.closed(); }
/** open button */
public void open() { _mode.open(); }
/** on/off button */
public void power() { _mode.power(); }
/** Timer (one tick per second). */
public void tick() { _mode.tick(); }
/**
* Switch mode. Note that this interface is public.
* @param mode the new mode.
*/
public void setState(State mode) {
_mode = mode;
}
}
|
A base de definição para os estado é como se indica de seguida. Contém, como se pode inferir da classe anterior, os métodos que dependem do estado da máquina (e que as subclasses de State codificam). Note-se que _machine foi definida como protected para simplificação da apresentação.
[Expand] class State
|
public abstract class State {
/** The washing machine. */
protected WashingMachine _machine;
/** @param machine is the washing machine. */
public State(WashingMachine machine) { _machine = machine; }
/** Behaviour for closing. */
public abstract void closed();
/** Behaviour for open. */
public abstract void open();
/** Behaviour for on/off. */
public abstract void power();
/** Behaviour for ticking. */
public abstract void tick();
}
|
As subclasses definidas para o problema cobrem as seguintes situações: porta aberta (máquina necessariamente desligada); porta fechada (máquina não iniciou lavagem ou espera terminou); máquina a lavar (5400 impulsos ou interrupção via botão on/off); espera depois da lavagem (120 impulsos).
As mensagens são apresentadas apenas por claridade e não são necessárias (excepto onde indicado no enunciado).
Note-se ainda que seria possível factorizar o código de gestão dos impulsos.
[Expand] class Open
|
public class Open extends State {
/**
* @param machine
*/
public Open(WashingMachine machine) {
super(machine);
System.out.println("** OPEN MODE: reached.");
}
/**
* @see State#closed()
*/
@Override
public void closed() {
System.out.println("** OPEN MODE: closed sensor activated.");
System.out.println("** OPEN MODE: switching to closed/idle mode.");
_machine.setState(new ClosedIdle(_machine));
}
/**
* @see State#open()
*/
@Override
public void open() {
System.out.println("** OPEN MODE: open button pressed (ignored).");
}
/**
* @see Washing#power()
*/
@Override
public void power() {
System.out.println("** OPEN MODE: power button pressed (ignored).");
}
/**
* @see State#tick()
*/
@Override
public void tick() {
System.out.println("** OPEN MODE: tick received (ignored).");
}
}
|
[Expand] class ClosedIdle
|
public class ClosedIdle extends State {
/**
* @param machine
*/
public ClosedIdle(WashingMachine machine) {
super(machine);
System.out.println("** CLOSED/IDLE: reached.");
}
/**
* @see State#closed()
*/
@Override
public void closed() {
System.out.println("** CLOSED/IDLE MODE: closed sensor activated (ignored).");
}
/**
* @see State#open()
*/
@Override
public void open() {
System.out.println("** CLOSED/IDLE MODE: open button pressed.");
System.out.println("** CLOSED/IDLE MODE: switching to open mode.");
_machine.setState(new Open(_machine));
}
/**
* @see Washing#power()
*/
@Override
public void power() {
System.out.println("** CLOSED/IDLE MODE: power (on) button pressed.");
System.out.println("** CLOSED/IDLE MODE: switching to washing mode.");
_machine.setState(new Washing(_machine));
}
/**
* @see State#tick()
*/
@Override
public void tick() {
System.out.println("** CLOSED/IDLE MODE: tick received (ignored).");
}
}
|
[Expand] class Washing
|
public class Washing extends State {
/**
* Do not stay in this state after ticking this much.
*/
private int MAX_TICKS = 5400;
/**
* How many ticks have we already counted?
*/
private int _ticks = 0;
/**
* @param machine
*/
public Washing(WashingMachine machine) {
super(machine);
System.out.println("** WASHING MODE: reached.");
}
/**
* @see State#closed()
*/
@Override
public void closed() {
System.out.println("** WASHING MODE: closed sensor activated (ignored).");
}
/**
* @see State#open()
*/
@Override
public void open() {
System.out.println("** WASHING MODE: open button pressed (ignored).");
}
/**
* @see State#power()
*/
@Override
public void power() {
System.out.println("** WASHING MODE: power (off) button pressed.");
System.out.println("** WASHING MODE: switching to wait mode.");
_machine.setState(new Wait(_machine));
}
/**
* @see State#tick()
*/
@Override
public void tick() {
System.out.println("** WASHING MODE: tick: " + _ticks);
_ticks++;
if (_ticks >= MAX_TICKS) {
System.out.println("** WASHING MODE: switching to wait mode.");
_machine.setState(new Wait(_machine));
}
}
}
|
[Expand] class Wait
|
public class Wait extends State {
/**
* Do not stay in this state after ticking this much.
*/
private int MAX_TICKS = 120;
/**
* How many ticks have we already counted?
*/
private int _ticks = 0;
/**
* @param machine
*/
public Wait(WashingMachine machine) {
super(machine);
System.out.println("** WAIT MODE: reached.");
}
/**
* @see State#closed()
*/
@Override
public void closed() {
System.out.println("** WAIT MODE: closed sensor activated (ignored).");
}
/**
* @see State#open()
*/
@Override
public void open() {
System.out.println("** WAIT MODE: open button pressed (ignored).");
}
/**
* @see Wait#power()
*/
@Override
public void power() {
System.out.println("** WAIT MODE: power button pressed (ignored).");
}
/**
* @see State#tick()
*/
@Override
public void tick() {
System.out.println("** WAIT MODE: tick: " + _ticks);
_ticks++;
if (_ticks >= MAX_TICKS) {
System.out.println("** WAIT MODE: switching to idle mode.");
_machine.setState(new ClosedIdle(_machine));
}
}
}
|