Programa Exemplo em Java

- O código abaixo não inclui sincronização devido a acessos concorrentes, nem
tratamento de persistência
- O código abaixo é diferente do código do livro
- Usa interfaces para desacoplar classes
- Apenas as interfaces externas foram definidas de forma a produzir a documentação
externa de quem usa as classes (ver documentação externa)
- Outras interfaces (internas) poderiam ser definidas para ter mais polimorfismo dentro do
pacote
- Inclui comentários javadoc para produzir documentação automaticamente
- Alguns modificadores de acesso (public, ...) foram alterados
- Usa Factory Methods (ver Design Patterns, em outro capítulo)
- Alguns métodos faltam no livro
- Exemplo: Loja tem que ter um getCatálogoDeProdutos(), senão a camada de interface com
o usuário não consegue obter a descrição de um produto com dado UPC para exibir ao
cliente
- Está em português
- Acentuação é usada em atributos e métodos mas não em nomes de classes e interfaces
porque, neste último caso, o nome do arquivo é igual à classe/interface e quero evitar
acentuação em nomes de arquivos (portabilidade)
- Tem tratamento de erro completo com 3 tipos de exceções
- Falta tratar mais um ou dois erros possíveis que estou deixando para o aluno descobrir
(e tratar!)
- O resultado é um código mais profissional
- Porém, as coisas sempre podem ser melhoradas
- Por exemplo: o uso de float para representar valores monetários não foi uma boa
decisão do autor Larman
- Por quê?
- Como você faria?
Documentação
- A documentação externa está aqui
- Observe que nesta documentação, há apenas a informação que pode ser usada "de
fora", isto é, pelas classes da interface do usuário
- O único objeto que pode ser criado é uma Loja
- A partir da Loja, pode-se obter um TPDV, ou um catálogo de produtos para fazer as
outras operações associada à interface com o usuário
- A documentação interna está aqui
- Útil para os desenvolvedores do pacote
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