Programa Exemplo em Java

codificacao.gif (9448 bytes)

Documentação

Interface IPagamento

package tpdv;

/**
 * Interface para qualquer tipo de pagamento.
 *
 * @author Jacques Philippe Sauvé, jacques@dsc.ufpb.br
 * @version 1.0
 */
interface IPagamento {
    /**
     * Retorna o valor entregue pelo cliente para pagar a venda.
     * @return O valor entregue pelo cliente para pagar a venda.
     */
    float getValor();
}

Classe Pagamento

package tpdv;

/**
 * Classe que representa um pagamento feito para uma venda.
 *
 * @author Craig Larman, Jacques Philippe Sauvé, jacques@dsc.ufpb.br
 * @version 1.0
 */
class Pagamento implements IPagamento {
    /**
     * O valor do pagamento de uma venda.
     */
    private float valor;

    /**
     * Cria um pagamento.
     * @param valorEntregue O valor entregue para pagar a venda.
     */
    public Pagamento(float valorEntregue) {
        this.valor = valorEntregue;
    }

    /**
     * Cria um pagamento.
     * @param valorEntregue O valor entregue para pagar a venda.
     */
    public Pagamento(double valorEntregue) {
        this.valor = (float)valorEntregue;
    }

    /**
     * Retorna o valor entregue para pagar a venda.
     * @return O valor entregue para pagar a venda.
     */
    public float getValor() { return valor; }
}

Interface IEspecProduto

package tpdv;

/**
 * Interface para qualquer tipo de especificação de produto.
 *
 * @author Jacques Philippe Sauvé, jacques@dsc.ufpb.br
 * @version 1.0
 */
public interface IEspecProduto {
   /**
    * Obtem o Universal Product Code (UPC) do produto.
    * @return O Universal Product Code (UPC) do produto.
    */
   int getUPC();

   /**
    * Obtem o preço do produto.
    * @return O preço do produto.
    */
   float getPreço();
   
   /**
    * Obtem a descrição do produto.
    * @return A descrição do produto.
    */
   String getDescrição();
}

Classe EspecificacaoDeProduto

package tpdv;

/**
 * Classe que representa uma especificação de um produto do catálogo de produtos.
 *
 * @author Craig Larman, Jacques Philippe Sauvé, jacques@dsc.ufpb.br
 * @version 1.0
 */
class EspecificacaoDeProduto implements IEspecProduto {
    /**
     * O Universal Product Code (UPC) do produto.
     */
    private int upc;
    /**
     * O preço do produto.
     */
    private float preço;
    /**
     * A descrição do produto.
     */
    private String descrição;

    /**
     * Cria uma especificação de produto.
     * @param upc O Universal Product Code do produto.
     * @param preço O preço do produto.
     * @param descrição A descrição do produto.
     */
    public EspecificacaoDeProduto(int upc, float preço, String descrição) {
        this.upc = upc;
        this.preço = preço;
        this.descrição = descrição;
    }

    /**
     * Cria uma especificação de produto.
     * @param upc O Universal Product Code do produto.
     * @param preço O preço do produto.
     * @param descrição A descrição do produto.
     */
    public EspecificacaoDeProduto(int upc, double preço, String descrição) {
        this(upc, (float)preço, descrição);
    }

    /**
     * Obtem o Universal Product Code do produto.
     * @return O Universal Product Code do produto.
     */
    public int getUPC() { return upc; }

    /**
     * Obtem o preço do produto.
     * @return O preço do produto.
     */
    public float getPreço() { return preço; }

    /**
     * Obtem a descrição do produto.
     * @return A descrição do produto.
     */
    public String getDescrição() { return descrição; }
}

Interface ICatalogoDeProdutos

package tpdv;

/**
 * Interface para qualquer tipo de Catálogo de Produtos
 *
 * @author Jacques Philippe Sauvé, jacques@dsc.ufpb.br
 * @version 1.0
 */
public interface ICatalogoDeProdutos {
    /**
     * Obtem a especificação de produto, dado o Universal Product Code (UPC)
     * @param upc O Universal Product Code (UPC) do produto desejado
     * @return A especificação de produto, dado o Universal Product Code (UPC)
     */
    public IEspecProduto getEspecificação(int upc) throws ProdutoInexistenteException;
}

Classe CatalogoDeProdutos

package tpdv;

import java.util.*;

/**
 * Classe que representa um catálogo de produtos.
 * Um catálogo contém várias especificações de produtos.
 *
 * @author Craig Larman, Jacques Philippe Sauvé, jacques@dsc.ufpb.br
 * @version 1.0
 */
class CatalogoDeProdutos implements ICatalogoDeProdutos {
    /**
     * O catálogo de produtos é guardado aqui.
     */
    private Map especsProdutos = new HashMap();

    /**
     * Cria um catálogo de produtos. Esta versão não trata de persistência.
     * O catálogo é fixo e criado no construtor.
     */
    public CatalogoDeProdutos() {
        int upc1 = 100;
        especsProdutos.put(new Integer(upc1),
                           makeEspecProduto(upc1, (float)1.99, "produto 1"));
        int upc2 = 200;
        especsProdutos.put(new Integer(upc2),
                           makeEspecProduto(upc2, (float)3.49, "produto 2"));
    }

    /**
     * Obtém a especificação de um produto.
     * @param upc o Universal Product Code do produto cuja especificação se deseja.
     * @return A especificação do produto desejado.
     */
    public IEspecProduto getEspecificação(int upc) throws ProdutoInexistenteException {
        IEspecProduto espec = (IEspecProduto)especsProdutos.get(new Integer(upc));
        if(espec == null) {
            throw new ProdutoInexistenteException("Produto inexistente, UPC: " + upc);
        }
        return espec;
    }

    // factory method
    protected IEspecProduto makeEspecProduto(int upc, float preço, String descrição) {
        return new EspecificacaoDeProduto(upc, preço, descrição);
    }
}

Classe ProdutoInexistenteException

package tpdv;

/**
 * Exceção indicando produto inexistente no catálogo de produtos.
 *
 * @author Jacques Philippe Sauvé, jacques@dsc.ufpb.br
 * @version 1.0
 */
public class ProdutoInexistenteException extends TPDVException {
    /**
     * Cria uma exceção de produto inexistente
     * @param mensagem Mensagem de erro imprimível
     */
    public ProdutoInexistenteException(String mensagem) {
        super(mensagem);
    }
}

Interface ILinhaDetalhe

package tpdv;

/**
 * Interface para qualquer tipo de linha de detalhe de uma venda.
 *
 * @author Jacques Philippe Sauvé, jacques@dsc.ufpb.br
 * @version 1.0
 */
interface ILinhaDetalhe {
    /**
     * Retorna o subtotal da venda para os itens correspondendo a esta linha de detalhe.
     * @return O subtotal da venda para os itens correspondendo a esta linha de detalhe.
     */
    float subTotal();
}

Classe LinhaDetalheVenda

package tpdv;

/**
 * Classe que representa uma linha de detalhe de uma venda.
 *
 * @author Craig Larman, Jacques Philippe Sauvé, jacques@dsc.ufpb.br
 * @version 1.0
 */
class LinhaDetalheVenda implements ILinhaDetalhe {
    /**
     * A quantidade de itens (do mesmo produto) neste detalhe de venda.
     */
    private int quantidade;
    /**
     * A especificação do produto sendo comprado.
     */
    private IEspecProduto espec;

    /**
     * Cria uma linha de detalhe de uma venda.
     * @param espec A especificação do produto sendo comprado.
     * @param quantidade A quantidade de itens (do mesmo produto) sendo comprados
     */
    public LinhaDetalheVenda(IEspecProduto espec, int quantidade) {
        this.espec = espec;
        this.quantidade = quantidade;
    }

    /**
     * Informa o subtotal da venda correspondendo a esta linha de detalhe.
     * @return O subtotal da venda correspondendo a esta linha de detalhe.
     */
    public float subTotal() {
        return quantidade * espec.getPreço();
    }
}

Interface IVenda

package tpdv;

/**
 * Interface externa para qualquer tipo de venda.
 *
 * @author Craig Larman, Jacques Philippe Sauvé, jacques@dsc.ufpb.br
 * @version 1.0
 */
public interface IVenda {
    /**
     * Retorna o troco da venda, após fazer um pagamento de uma venda.
     * @return o troco da venda, após fazer um pagamento de uma venda.
     */
    float getTroco();

    /**
     * Retorna o valor total da venda, até agora.
     * @return o valor total da venda, até agora.
     */
    float total();
}

Classe Venda

package tpdv;

import java.util.*;

/**
 * Classe que representa uma venda de produtos feita através de um TPDV.
 * Uma venda é composta de várias linhas de detalhe.
 * Enquanto a venda não terminou, tais linhas de detalhe podem ser criadas.
 * Um pagamento pode ser feita para pagar a venda.
 * Pode-se calcular o troco a ser entregue ao cliente.
 *
 * @author Craig Larman, Jacques Philippe Sauvé, jacques@dsc.ufpb.br
 * @version 1.0
 */
class Venda implements IVenda {
    /**
     * As linhas de detalhe da venda.
     */
    private List linhasDetalhe = new Vector();
    /**
     * A data da venda.
     */
    private Date data = new Date(); // hoje
    /**
     * Indica se a venda terminou.
     */
    private boolean isTerminada = false;
    /**
     * O pagamento efetuado para a venda.
     */
    private IPagamento pagamento;

    /**
     * Calcula o valor total da venda.
     * @return O valor total da venda.
     */
    public float total() {
        float total = (float)0.0;
        Iterator it = linhasDetalhe.iterator();
        while(it.hasNext()) {
            total += ((ILinhaDetalhe)it.next()).subTotal();
        }
        return total;
    }

    /**
     * Calcule o troco para a venda, após um pagamento.
     * @return O troco para a venda.
     */
    public float getTroco() {
        return pagamento.getValor() - total();
    }

    /**
     * Chamado para indicar que a venda terminou.
     */
    void terminou() {
        isTerminada = true;
    }

    /**
     * Obtém o status da venda.
     * @return true se a venda terminou; false caso contrário.
     */
    boolean isTerminada() {
        return isTerminada;
    }

    /**
     * Cria uma linha de detalhe para a venda.
     * @param espec A especificação do produto sendo comprado.
     * @param quantidade A quantidade de itens (do mesmo produto) sendo comprados.
     */
    void criaLinhaDetalhe(IEspecProduto espec, int quantidade) {
        linhasDetalhe.add(makeLinhaDetalhe(espec, quantidade));
    }

    /**
     * Faz um pagamento para a venda.
     * @param valorEntregue O valor entregue pelo cliente para pagar a venda.
     */
    void façaPagamento(float valorEntregue) throws PagamentoInsuficienteException {
        if(valorEntregue < total()) {
            throw new PagamentoInsuficienteException("Pagamento insuficiente");
        }
        pagamento = makePagamento(valorEntregue);
    }

    // factory methods
    protected ILinhaDetalhe makeLinhaDetalhe(IEspecProduto espec, int quantidade) {
        return new LinhaDetalheVenda(espec, quantidade);
    }

    protected IPagamento makePagamento(float valorEntregue) {
        return new Pagamento(valorEntregue);
    }
}

Classe NaoHaVendaException

package tpdv;

/**
 * Exceção indicando operação necessitando de venda sem venda ativa
 *
 * @author Jacques Philippe Sauvé, jacques@dsc.ufpb.br
 * @version 1.0
 */
public class NaoHaVendaException extends TPDVException {
    /**
     * Cria uma exceção de operação necessitando de venda sem venda ativa
     * @param mensagem Mensagem de erro imprimível
     */
    public NaoHaVendaException(String mensagem) {
        super(mensagem);
    }
}

Classe PagamentoInsuficienteException

package tpdv;

/**
 * Exceção indicando pagamento insuficiente para uma venda.
 *
 * @author Jacques Philippe Sauvé, jacques@dsc.ufpb.br
 * @version 1.0
 */
public class PagamentoInsuficienteException extends TPDVException {
    /**
     * Cria uma exceção de pagamento insuficiente
     * @param mensagem Mensagem de erro imprimível
     */
    public PagamentoInsuficienteException(String mensagem) {
        super(mensagem);
    }
}

Interface ITPDV

package tpdv;

/**
 * Interface para qualquer tipo de Terminal Ponto De Venda (TPDV).
 * Um TPDV é usado para fazer uma venda (uma única venda de cada vez).
 * Itens podem ser comprados até o final da venda.
 * Um pagamento pode ser feito para a venda corrente.
 *
 * @author Jacques Philippe Sauvé, jacques@dsc.ufpb.br
 * @version 1.0
 */
public interface ITPDV {
    /**
     * Obtém a venda corrente sendo realizada pelo TPDV.
     * @return A venda corrente sendo realizada pelo TPDV.
     */
    IVenda getVenda();

    /**
     * Chamado para indicar que a venda terminou.
     */
    void fimDeVenda() throws NaoHaVendaException;

    /**
     * Chamado para adicionar à venda corrente um número de itens sendo comprados.
     * @param upc O Universal Product Code do item sendo comprado.
     * @param quantidade O número de itens sendo comprados.
     */
    void entraItem(int upc, int quantidade) throws ProdutoInexistenteException;
    
    /**
     * Realiza um pagamento para uma venda.
     * @param valorEntregue O valor entregue pelo cliente para pagar a venda.
     */
    void façaPagamento(float valorEntregue) throws PagamentoInsuficienteException;
}

Classe TPDV

package tpdv;

/**
 * Classe que implementa um Terminal Ponto De Venda (TPDV).
 * Um TPDV é usado para fazer uma venda (uma única venda de cada vez).
 * Itens podem ser comprados até o final da venda.
 * Um pagamento pode ser feito para a venda corrente.
 *
 * @author Craig Larman, Jacques Philippe Sauvé, jacques@dsc.ufpb.br
 * @version 1.0
 */
class TPDV implements ITPDV {
    /**
     * O catálogo de produtos que podem ser vendidos neste TPDV.
     */
    private ICatalogoDeProdutos catálogo;
    /**
     * A venda corrente sendo realizada no TPDV.
     */
    private IVenda venda;

    /**
     * Cria um TPDV.
     * @param catálogo Um catálogo de produtos que podem ser adquiridos neste TPDV.
     */
    public TPDV(ICatalogoDeProdutos catálogo) {
        this.catálogo = catálogo;
        venda = null;
    }

    /**
     * Obtém a venda corrente sendo realizada no TPDV.
     * @return A venda corrente sendo realizada no TPDV.
     */
    public IVenda getVenda() {
        return venda;
    }

    /**
     * Quando chamado, indica que a venda corrente sendo realizada no TPDV terminou.
     */
    public void fimDeVenda() throws NaoHaVendaException {
        if(venda == null) {
            throw new NaoHaVendaException("Nao ha venda iniciada");
        }
        venda.terminou();
    }

    /**
     * Informa um produto e a quantidade de itens deste produto sendo comprados na venda corrente.
     * Caso a venda anterior já tenha terminado, uma nova Venda é criada.
     * @param upc O Universal Product Code (UPC) do produto sendo comprado.
     * @param quantidade A quantidade de itens sendo comprados.
     */
    public void entraItem(int upc, int quantidade) throws ProdutoInexistenteException {
        if(isNovaVenda()) {
            venda = makeVenda();
        }
        venda.criaLinhaDetalhe(catálogo.getEspecificação(upc), quantidade);
    }

    /**
     * Realiza um pagamento para a venda corrente do TPDV.
     * @param valorEntregue O valor entregue pelo cliente para pagar a venda.
     */
    public void façaPagamento(float valorEntregue) throws PagamentoInsuficienteException {
        venda.façaPagamento(valorEntregue);
    }

    // visibilidade de package para poder testar
    boolean isNovaVenda() {
        return venda == null || venda.isTerminada();
    }

    // factory method
    protected IVenda makeVenda() { return new Venda(); }
}

Classe Loja

package tpdv;

/**
 * Classe que implementa uma Loja. Cada loja tem um catálogo de produtos e um único TPDV.
 *
 * @author Craig Larman, Jacques Philippe Sauvé, jacques@dsc.ufpb.br
 * @version 1.0
 */
public class Loja {
    /**
     * O catálogo de produtos da loja.
     */
    private ICatalogoDeProdutos catálogo;
    /**
     * O terminal ponto de venda (TPDV) da loja.
     * Uma loja só tem um único TPDV.
     */
    private ITPDV tpdv;

    /**
     * Cria uma loja. O catálogo de produtos e o TPDV são automaticamente criados.
     * @param valorEntregue O valor entregue para pagar a venda.
     */
    public Loja() {
        catálogo = makeCatálogo();
        tpdv = makeTPDV(catálogo);
    }

    /**
     * Obtem o TPDV da loja.
     * @return O TPDV da loja.
     */
    public ITPDV getTPDV() { return tpdv; }

    /**
     * Obtem o TPDV da loja.
     * @return O TPDV da loja.
     */
    public ICatalogoDeProdutos getCatálogoDeProdutos() { return catálogo; }

    // factory methods
    protected ICatalogoDeProdutos makeCatálogo() {
        return new CatalogoDeProdutos();
    }

    protected ITPDV makeTPDV(ICatalogoDeProdutos catálogo) {
        return new TPDV(catálogo);
    }
}

impl-2 programa anterior próxima