Introdução

Na concretização da interface com o utilizador deve ser aplicado a Framework de Interacção com o Utilizador po-uilib.jar. Esta framework é explicada com detalhe no seguinte documento:  desenvolvimentoAplicaçõesPO.pdf.

Resumidamente, a funcionalidade de mostrar as operações disponíveis e executar a opção escolhida pelo utilizador deve ser concretizada pelas classes Menu e Command. A classe Command representa uma operação genérica que pode ser executada sobre uma dada entidade. Cada comando sabe o título da operação que representa (é utilizado no menu para indicar os títulos das operações disponíveis). Esta classe abstracta define o método abstracto execute que executa a operação. Cada operação a disponibilizar num menu terá que ser concretizada numa sua subclasse. A classe Menu recebe um vector de comandos e mostra os títulos destes comandos por forma a que os utilizadores saibam as operações disponíveis. Cabe ainda ao menu executar o comando correspondente à opção escolhida pelo utilizador. 

Por forma a centralizar (e assim permitir a reutilização de código) a interface com o utilizador, existe uma classe, chamada Form, que é responsável pela interacção com o utilizador. Esta classe fornece métodos que permitem escrever uma cadeia de caracteres (prompt) e ler um determinado tipo de dados inserido pelo utilizador consoante a instância de Input escolhida. Esta classe concentra todas as operações de leitura de dados (fornecidos pelo utilizador). Os dados lidos são validados, i.e., apenas são aceites dados correctos. No caso do utilizador inserir dados inválidos, é pedida a respectiva reintrodução. Estas classes permitem ainda ler os dados a introduzir pelo utilizador via ficheiro e escrever o resultado da execução da aplicação num ficheiro em vez de escrever no standard output. O nome destes ficheiros são indicados através das propriedades in e out. Caso não sejam indicadas, são utilizados os valores por omissão (standard input e standard output).

A apresentação de dados ao utilizador deve ser via classe Display.

Exemplo

De seguida descreve-se um pequeno exemplo de aplicação desta framework. O objectivo é construir uma aplicação com um menu com duas opções. Uma opção permite que o utilizador escreva um número inteiro e a outra opção apresenta todos os números que foram inseridos previamente pelo utilizador.

Nesta aplicação simples apenas existe uma entidade no domínio da aplicação, designada por CoreEntity. Esta entidade mantém os números inseridos pelo utilizador: CoreEntity.java

A classe MainMenu é responsável por definir o menu da aplicação. Um menu é representado por uma subclasse de Menu apenas sendo necessário definir um único método, o construtor da subclasse. Este construtor tem como responsabilidade principal especificar qual é o título do menu e as suas opções. A inicialização destes dois atributos, que pertencem à superclasse Menu, é feita através da invocação do construtor da super classe que acontece na primeira linha de código do construtor da classe derivada .

As várias opções de um menu são concretizadas através de classes derivadas de Command concretizadas pela equipa de desenvolvimento. Normalmente estas classes apenas têm dois métodos:

  • Construtor, que serve para inicializar os atributos das instâncias destas classes. Estes atributos são o título da opção (cadeia de caracteres apresentada ao utilizador para representar a opção) e um objecto (normalmente uma entidade do domínio) no contexto do qual o comando é executado.
  • Substituição do método abstracto public void execute(). Este é o método responsável por realizar a funcionalidade associada à opção em causa. Normalmente, este método envolve a realização de um conjunto de perguntas feitas ao utilizador (o que é realizado através das classes Form e os diferentes tipos de Input, de seguida invoca-se um ou mais métodos sobre entidades do domínio e finalmente podem-se apresentar resultados ao utilizador através da classe Display.
A primeira opção a concretizar adiciona um número inteiro à entidade do domínio. A subclasse de Command a concretizar consegue aceder à entidade do domínio em causa através do método entity() herdado de Command . Este método devolve a instância associada no processo de construção do comando via invocação do construtor da super classe Command. O código desta classe é o seguinte: AddNumber.java.
A segunda opção da aplicação, concretizada na classe ListNumbers, consiste em apresentar ao utilizador todos os números, um por linha, adicionados à única entidade do domínio. Tal como no caso anterior, esta entidade está associada ao comando que concretiza esta opção. A associação é novamente realizada no construtor da classe derivada de Command. Depois, no método execute pode-se aceder a esta entidade do domínio via método entity(). O método execute utiliza a entidade Display para apresentar os números já inseridos ao utilizador. Cada linha a apresentar ao utilizador é adicionada à instância de Display criada via invocação do método addNewLine sobre esta instância, indicando como argumento deste método a cadeia de caracteres a adicionar. Após terem sido adicionadas todas as linhas de texto a apresentar à instância de Display, deve-se então invocar o método display() sobre esta instância para que todo o texto inserido seja finalmente apresentado ao utilizador. O código desta classe é o seguinte: ListNumbers.

A classe que concretiza o menu da aplicação tem que criar um vector de Command's com duas instâncias, uma de AddNumber e outra de ListNumbers, que vão representar as opções do menu a apresentar ao utilizador. O código desta classe é o seguinte:  MainMenu.java.
Finalmente, para começarmos esta aplicação é necessário criar uma instância e MainMenu e abri-lo. Abrir um menu corresponde a invocar o método open sobre a instância que representa o menu. O menu vai sendo apresentado enquanto o utilizador não escolher a opção 0 (zero). A criação deste menu e a sua abertura é realizada no método main da classe Main. Código desta classe: Main.java.

É possível ter submenus, ou seja, um menu dentro de outro menu. Isto corresponde a ter uma opção de um menu cujo método execute cria um novo menu e abre o menu. Por exemplo, a seguinte classe ShowMenu corresponde a um comando que cria uma instância de MainMenu e mostra as opções deste menu. Agora é necessário alterar a classe MainMenu para que esta passe a representar um menu com três opções, sendo necessário criar um vector com três instâncias de Command:

    public MainMenu(CoreEntity object) {
        super("MENU PRINCIPAL", new Command<?>[] {
                    new AddNumber(object), new ListNumbers(object), new ShowMenu(object)
                    }); 
    }
Neste caso está-se a definir um submenu que é igual ao menu principal.