aluno: Ricardo Tominaga
ano/sem: 2008/2o.
data do laboratório (num. da semana) : 09/10/2008 (2)
Introdução
Neste laboratório foi criada uma classe que possibilita a construção de uma máquina de estados. A sua construção se dá através da definição dos estados e transições, bem como ações de estado, evento e de guarda. A criação da classe em si possibilitou o contato com dois padrões de projeto: Observer e command. Como aplicação foi implementada a máquina de estados proposta pelo roteiro e, além disso, foi implementada uma máquina de estados que representa, de forma simplificada, o acesso de um banco a um cofre eletrônico, a segurança do banco e algumas tentativas de se "roubar" tal cofre.
Desenvolvimento
Criação do package stateMachine
Antes da criação da classe StateMachine e, conseqüentemente, seus métodos, definiu-se três outras classes que auxiliariam sua construção: State, Event e Transition. Felizmente, o diagrama de classes ficou muito parecido com o desenhado durante a aula, considerando-se o relacionamento entre as três classes "auxiliares" e a classe StateMachine, FIG.1.

FIG.1
Classe State
Classe que define os atributos e métodos de um estado. No caso, escolheu-se como atributos o nome do estado, uma vez que as funções da classe StateMachine trabalham com o nome (string) como parâmetro, e o StateCommand.
Classe Transition
Classe que especifica uma única transição, contendo como atributos estado inicial e estado final apenas.
Classe Event
Classe de suma importância e que facilita grande parte do trabalho na definição da classe StateMachine. Nessa classe, foi utilizado extensivamente um objeto peculiar, o HashMap, que relaciona uma "key" a um "value" de tipos escolhidos pelo programador. Isso facilita muito o desenvolvimento dos métodos em comparação com o tipo "vector". Cada objeto instanciado da classe Event conterá um nome, um evento de guarda e um evento de "sucesso" e principalmente um HashMap que relaciona univocamente determinado estado e transição. Um método muito importante foi o appendTransition que já deu seguimento para a criação dos métodos createEvent (em todos as suas sobrecargas) bem como appendTransitionToEvent.
Padrões utilizados
Observer
Pode-se resumir o padrão Observer com as seguintes linhas de código:
//Comportamento de observável public void registerObserver(Observer observer){ this.observer.add(observer); } protected void notifyObservers(){ for(Observer obs : this.observer){ obs.update(this,currentState.getName()); } }
public interface Observer { void update(StateMachine sm, String newStateName); }
A função notifyObservers "executa" o método update que é implementado nos observadores, os quais "herdam" a interface Observer. Isso garante que o próprio objeto em mudança, o observado, "avise" a todos os seus observadores que está mudando e, além disso, não importa como a função update é implementada no observador.
Command
Pode-se resumir o padrão Command com as seguintes linhas de código:
public abstract class EventCommand { protected StateMachine machine; public EventCommand(StateMachine machine) { this.machine = machine; } public abstract void execute(String previousState); }
public abstract class StateCommand { protected StateMachine machine; public StateCommand(StateMachine machine) { this.machine = machine; } public abstract void execute(); }
O padrão command é utilizado quando se deseja definir comportamentos diferentes a objetos de instância de um mesmo tipo. No caso, eventos diferentes, os quais são do mesmo tipo Event, teriam comportamentos diferentes, por exemplo. Além disso, a definição do comportamento é feita através de classes anônimas.
Informações "escondidas"
O fato de toda a estrutura da máquina de estados não poder ser acessada diretamente, apenas através dos métodos da classe, garantiu um grande encapsulamento e conseqüente simplicidade da interface da classe StateMachine, com métodos bem claros e intuitivos de se usar. A variedade de comportamentos para os aventos e estados só foi possível com a utilização do padrão command. A utilização do padrão observer permite a interação de duas ou mais máquinas de estado, de forma que, o update atua no disparo de um evento em outra, um exemplo disso está na aplicação do Cofre Eletrônico, mais especificamente na atuação da Segurança.
Teste bem sucedido da classe StateMachine
O package passou no teste!

FIG.2
Exemplo dado
Diagrama e execução do exemplo dado FIG.3.

FIG.3
O exemplo dado mostra a interação de duas máquinas de estado. Uma representado o professor e a outra a turma, sendo que o comportamento da turma determina o estado do professor.
Aplicação Cofre Eletrônico
A aplicação do package desenvolvido foi em um cofre eletrônico. Para ser aberto, o cofre precisa de uma série de procedimentos. No caso de uma tentativa de burlar algum dos procedimentos de biometria (digital, voz, retina) o cofre entra em alerta, o que aciona o observador segurança, que, por sua vez, envia viaturas para averiguação e dispara o evento para proteger o cofre, assim, volta-se ao estado inicial "trancado".
Abertura normal do cofre FIG.4

FIG.4
Tentativa de entrada de senha incorreta e tentativa de burlar a análise da retina FIG.5

FIG.5
Tentativa burlar a análise da voz FIG.6

FIG.6
Conclusão
Aplicação clara do padrão Observer e Command. A classe StateMachine tem valor didático alto, no entanto, aplicabilidade baixa na visão do autor. Deve existir uma forma de armazenamento da máquina que não utilize tanto o objeto HashMap, mas foi a melhor escolha no aspecto organização de código, uma vez que a utilização do objeto vector implicaria em diversas rotinas de busca e verificação de existência, que aumentaria razoavelmente o código.





