Lab3 Ricardo Tominaga

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.

classeStateMachine.jpg

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!

classeTeste.jpg

FIG.2

Exemplo dado

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

testExemplo.jpg

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

testeCofre1.jpg

FIG.4

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

testeCofre2.jpg

FIG.5

Tentativa burlar a análise da voz FIG.6

testeCofre4.jpg

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.

Add a New Comment
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License