Camada de serviços


A camada de serviços contém a concretização das várias opções oferecidas pelos vários menus da aplicação. Esta camada é composta essencialmente pelos vários comandos ou serviços que concretizam as opções disponibilizadas nos vários menus da aplicação. Esta camada interage com as outras duas camadas:

  • Pede e apresenta dados ao utilizador via camada de apresentação
  • Realiza pedidos às entidades do domínio por forma a aceder e/ou alterar o estado da aplicação.
Nesta secção apresentamos apenas parte do código desta camada. Os restantes comandos estão disponíveis no código disponibilizado com a concretização desta aplicação exemplo.

Listar os números inseridos

Este comando é responsável por apresentar todos os números guardados pela aplicação. A série de números é mantida pela classe IntegerManger da camada de lógica de negócio. Desta forma, a entidade receiver que deve estar associada a este comando é do tipo IntegerManager. A associação entre instâncias deste comando e o seu receiver é estabelecida no processo de criação de um comando pelo que o construtor desta classe deve ter o IntegerManager a associar como parâmetro. A concretização da funcionaldiade deste comando deve ser realizada no método execute(): primeiro, pede a lista de números inseridos pelo utilizador à entidade do domínio da aplicação que mantém a série de números inseridos pelo utilizador. Esta entidade é acedida através do atributo _receiver. Depois, constroi-se incrementalmente o texto a apresentar ao utilizador adicionando cada número da série numa linha separada através da invocação do método addLine sobre a instância de Display que está disponível para qualquer comando via atributo _display. Após se ter construído todo o texto, indica-se ao Display referenciado por _display para finalmente apresentar o texto final ao utilizador invocando o método display().

package ex.app.main;

import java.util.List;
import ex.core.IntegerManager;
import pt.tecnico.uilib.menus.Command;
import java.util.function.Predicate;
public class ListNumbers extends Command<IntegerManager> {        
  //Constructor
  public ListNumbers(IntegerManager ent) {
    super("Listar Números", ent, x -> return !ent.getNumbers().isEmpty() );
  }
  protected void execute() { // executed when this option is selected
    List<Integer> list = _receiver.getNumbers();
    
    for (Integer number : list)
      _display.addLine(number.toString());
    _display.display();
  }
}

O construtor desta classe não invoca o construtor usual da super classe (Command), utilizando outro que permite a especificação da visibilidade do comando a criar. Neste caso concreto, o comando criaodo só é visível caso a entidade receiver do comando tenha números. Se o IntegerManager não tiver nenhum número associado, então este comando não será visível quando o menu for apresentado.

Apresentar o menu de edição

Este comando é responsável por apresentar o menu de edição. Assim, a concretização do método execute() é muito simples: apenas tem que se criar uma instância de EditMenu (a classe que define o menu de edição) e abrir o menu através da invocação do método open() sobre o menu criado.


package ex.app.main;

import ex.core.IntegerManager;
import ex.app.edit.EditMenu;
import pt.tecnico.uilib.menus.Command;

public class ShowEditMenu extends Command<IntegerManager> {        
  //Constructor
  public ShowEditMenu(IntegerManager ent) {
    super("Abrir Menu Edição", ent);
  }
  
  protected void execute() { // executed when this option is selected
    EditMenu menu = new EditMenu(_receiver);
    menu.open();
  }
}

Esta funcionalidade pode ser concretizada de uma forma mais simples utilizando o comando DoOpenMenu já fornecedido pela framework, o qual concretiza um comando que corresponde a abrir um dado menu. Neste caso, a criação do menu principal deve criar uma instância de DoOpenmenu em vez de ShowEditMenu (que deixa de ser necessário e pode ser apagado):

package ex.app.main;

import ex.core.IntegerManager;
import pt.tecnico.uilib.menus.Menu;
import pt.tecnico.uilib.menus.DoOpenMenu;
import ex.app.edit.EditMenu;

public class MainMenu extends Menu {

    //Constructor
    public MainMenu(IntegerManager ent) {
        super("MENU PRINCIPAL",
              new ListNumbers(ent), new ShowNumberOfIntegers(ent), new DoOpenMenu("Abrir Menu Edição", new EditMenu(ent))
              //new ListNumbers(ent), new ShowNumberOfIntegers(ent), new ShowEditMenu(ent)
              );
    }
}

Adicionar um número 

Dado que apenas é necessário ler um inteiro, o formulário apenas irá conter um pedido do tipo InputInteger, o qual tem que ser criado e adicionado ao formulário. Uma forma mais rápida de especificar o código para criar o pedido e associá-lo ao formulário é utilizar um dos vários métodos add disponíveis na classe Form. Existe um método add para cada tipo de dados a inserir pelo utilizador. Neste exemplo é utilizado o método addInputInteger, o qual recebe a mensagem a colocar no pedido e cria o pedido, associa o pedido criado ao formulário e devolve uma referência para o pedido criado. Utilizando esta abordagem, o método execute do comando apenas terá que invocar o método parse sobre o formulário do comando e depois aceder ao valor inserido para cada pedido invocando método value() sobre o pedido.


package ex.app.edit;

import ex.core.IntegerManager;
import pt.tecnico.uilib.menus.Command;

public class AddNumber extends Command<IntegerManager> {
  //Constructor
  public AddNumber(IntegerManager ent) {
    super("Adicionar Número", ent);
    addIntegerField("number", "Introduza um número: ");
  }

  protected void execute() {  // executed when this option is selected
    Integer number = integerField("number");
    String message;

    if (_receiver.addNumber(number))
      message = "Número adicionado: " + number;
    else
      message = "Número não adicionado";

    _display.popup(message);
  }
}