diff --git a/src/com/lojaonline/LojaOnline.java b/src/com/lojaonline/LojaOnline.java new file mode 100644 index 0000000..d59dac2 --- /dev/null +++ b/src/com/lojaonline/LojaOnline.java @@ -0,0 +1,37 @@ +package com.lojaonline; + +import com.lojaonline.envio.GerenciadorEnvio; +import com.lojaonline.pagamento.*; +import com.lojaonline.pedido.Pedido; +import com.lojaonline.produtos.Produto; +import com.lojaonline.repositorio.EmMemoriaPedidoRepositorio; +import com.lojaonline.servicos.ServicoPedido; + +import java.util.List; + +public class LojaOnline { + public static void main(String[] args) { + var repo = new EmMemoriaPedidoRepositorio(); + + // Posso trocar o metodo de pagamento livremente (OCP + LSP) + PagamentoPort pagamento = new ProcessadorPagamento<>(new CartaoCredito()); + // PagamentoPort pagamento = new ProcessadorPagamento<>(new Pix()); + // PagamentoPort pagamento = new ProcessadorPagamento<>(new Boleto()); + + var envio = new GerenciadorEnvio(); + var servico = new ServicoPedido(repo, pagamento, envio); + + var itens = List.of( + new Produto("Motoserra", 1500.00), + new Produto("Capacete", 300.00), + new Produto("Luvas", 50.00) + ); + + var pedido = new Pedido(itens, "Rua das Flores, 123"); + long id = servico.criarNovoPedido(pedido); + servico.processarPedido(id); + servico.enviarPedido(id); + } +} + + diff --git a/src/com/lojaonline/envio/EnvioPort.java b/src/com/lojaonline/envio/EnvioPort.java new file mode 100644 index 0000000..dcaa297 --- /dev/null +++ b/src/com/lojaonline/envio/EnvioPort.java @@ -0,0 +1,6 @@ +package com.lojaonline.envio; + +// ISP: contrato mínimo para envio. +public interface EnvioPort { + void enviarPara(String endereco); +} diff --git a/src/com/lojaonline/envio/GerenciadorEnvio.java b/src/com/lojaonline/envio/GerenciadorEnvio.java new file mode 100644 index 0000000..928e8df --- /dev/null +++ b/src/com/lojaonline/envio/GerenciadorEnvio.java @@ -0,0 +1,8 @@ +package com.lojaonline.envio; + +public class GerenciadorEnvio implements EnvioPort { + @Override + public void enviarPara(String endereco) { + System.out.println("Enviando pedido para: " + endereco); + } +} diff --git a/src/com/lojaonline/pagamento/Boleto.java b/src/com/lojaonline/pagamento/Boleto.java new file mode 100644 index 0000000..d7cab88 --- /dev/null +++ b/src/com/lojaonline/pagamento/Boleto.java @@ -0,0 +1,8 @@ +package com.lojaonline.pagamento; + +public class Boleto implements MetodoPagamento { + @Override + public void processarPagamento(double valor) { + System.out.println("Boleto gerado e compensado: R$ " + valor); + } +} diff --git a/src/com/lojaonline/pagamento/CartaoCredito.java b/src/com/lojaonline/pagamento/CartaoCredito.java new file mode 100644 index 0000000..99dacda --- /dev/null +++ b/src/com/lojaonline/pagamento/CartaoCredito.java @@ -0,0 +1,8 @@ +package com.lojaonline.pagamento; + +public class CartaoCredito implements MetodoPagamento { + @Override + public void processarPagamento(double valor) { + System.out.println("Pagamento aprovado via Cartão de Crédito: R$ " + valor); + } +} diff --git a/src/com/lojaonline/pagamento/MetodoPagamento.java b/src/com/lojaonline/pagamento/MetodoPagamento.java new file mode 100644 index 0000000..77c7db0 --- /dev/null +++ b/src/com/lojaonline/pagamento/MetodoPagamento.java @@ -0,0 +1,6 @@ +package com.lojaonline.pagamento; + +// ISP: contrato pequeno e específico. +public interface MetodoPagamento { + void processarPagamento(double valor); +} diff --git a/src/com/lojaonline/pagamento/PagamentoPort.java b/src/com/lojaonline/pagamento/PagamentoPort.java new file mode 100644 index 0000000..81fe21e --- /dev/null +++ b/src/com/lojaonline/pagamento/PagamentoPort.java @@ -0,0 +1,6 @@ +package com.lojaonline.pagamento; + +// DIP: porta de alto nível para o serviço depender. +public interface PagamentoPort { + void pagar(double valor); +} diff --git a/src/com/lojaonline/pagamento/Pix.java b/src/com/lojaonline/pagamento/Pix.java new file mode 100644 index 0000000..2f0ab09 --- /dev/null +++ b/src/com/lojaonline/pagamento/Pix.java @@ -0,0 +1,8 @@ +package com.lojaonline.pagamento; + +public class Pix implements MetodoPagamento { + @Override + public void processarPagamento(double valor) { + System.out.println("Pagamento confirmado via PIX: R$ " + valor); + } +} diff --git a/src/com/lojaonline/pagamento/ProcessadorPagamento.java b/src/com/lojaonline/pagamento/ProcessadorPagamento.java new file mode 100644 index 0000000..26ea237 --- /dev/null +++ b/src/com/lojaonline/pagamento/ProcessadorPagamento.java @@ -0,0 +1,16 @@ +package com.lojaonline.pagamento; + +// LSP: qualquer MetodoPagamento pode ser plugado sem quebrar cliente. +// DIP/ISP: expõe apenas PagamentoPort para o serviço. +public class ProcessadorPagamento implements PagamentoPort { + private final T metodo; + + public ProcessadorPagamento(T metodo) { + this.metodo = metodo; + } + + @Override + public void pagar(double valor) { + metodo.processarPagamento(valor); + } +} diff --git a/src/com/lojaonline/pedido/Pedido.java b/src/com/lojaonline/pedido/Pedido.java new file mode 100644 index 0000000..15c660d --- /dev/null +++ b/src/com/lojaonline/pedido/Pedido.java @@ -0,0 +1,34 @@ +package com.lojaonline.pedido; + +import com.lojaonline.produtos.Produto; +import java.util.ArrayList; +import java.util.List; + +// SRP: dados e regras do pedido (sem pagar/enviar aqui). +public class Pedido { + private Long id; + private final List itens = new ArrayList<>(); + private StatusPedido status = StatusPedido.PENDENTE; + private final String enderecoEntrega; + + public Pedido(List itens, String enderecoEntrega) { + if (itens != null) itens.forEach(this.itens::add); + this.enderecoEntrega = enderecoEntrega; + } + + public Long getId() { return id; } + public void setId(Long id) { this.id = id; } + + public StatusPedido getStatus() { return status; } + public void setStatus(StatusPedido status) { this.status = status; } + + public String getEnderecoEntrega() { return enderecoEntrega; } + public List getItens() { return List.copyOf(itens); } + + public void addItem(Produto p) { itens.add(p); } + public void removerItem(Produto p) { itens.remove(p); } + + public double calcularTotal() { + return itens.stream().mapToDouble(Produto::getPreco).sum(); + } +} diff --git a/src/com/lojaonline/pedido/StatusPedido.java b/src/com/lojaonline/pedido/StatusPedido.java new file mode 100644 index 0000000..bbc84cf --- /dev/null +++ b/src/com/lojaonline/pedido/StatusPedido.java @@ -0,0 +1,5 @@ +package com.lojaonline.pedido; + +public enum StatusPedido { + PENDENTE, PAGO, ENVIADO, CANCELADO +} diff --git a/src/com/lojaonline/produtos/Produto.java b/src/com/lojaonline/produtos/Produto.java new file mode 100644 index 0000000..c0864fd --- /dev/null +++ b/src/com/lojaonline/produtos/Produto.java @@ -0,0 +1,18 @@ +package com.lojaonline.produtos; + +import java.util.Objects; + +// SRP: representa um produto. +public class Produto { + private final String nome; + private final double preco; + + public Produto(String nome, double preco) { + this.nome = Objects.requireNonNull(nome, "nome obrigatório"); + if (preco < 0) throw new IllegalArgumentException("Preço não pode ser negativo"); + this.preco = preco; + } + + public String getNome() { return nome; } + public double getPreco() { return preco; } +} diff --git a/src/com/lojaonline/repositorio/EmMemoriaPedidoRepositorio.java b/src/com/lojaonline/repositorio/EmMemoriaPedidoRepositorio.java new file mode 100644 index 0000000..760b710 --- /dev/null +++ b/src/com/lojaonline/repositorio/EmMemoriaPedidoRepositorio.java @@ -0,0 +1,33 @@ +package com.lojaonline.repositorio; + +import com.lojaonline.pedido.Pedido; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +// Implementação simples para rodar e testar sem BD/JPA. +public class EmMemoriaPedidoRepositorio implements PedidoRepositorio { + private final Map store = new ConcurrentHashMap<>(); + private long seq = 0L; + + @Override + public void salvar(Pedido pedido) { + if (pedido.getId() == null) { + seq++; + pedido.setId(seq); + } + store.put(pedido.getId(), pedido); + } + + @Override + public Optional buscarPorId(long id) { + return Optional.ofNullable(store.get(id)); + } + + @Override + public List buscarPorStatus(String status) { + return store.values().stream() + .filter(p -> p.getStatus().name().equalsIgnoreCase(status)) + .collect(Collectors.toList()); + } +} diff --git a/src/com/lojaonline/repositorio/PedidoRepositorio.java b/src/com/lojaonline/repositorio/PedidoRepositorio.java new file mode 100644 index 0000000..f3b4be7 --- /dev/null +++ b/src/com/lojaonline/repositorio/PedidoRepositorio.java @@ -0,0 +1,12 @@ +package com.lojaonline.repositorio; + +import com.lojaonline.pedido.Pedido; +import java.util.List; +import java.util.Optional; + +// ISP + DIP: contrato específico (nada de Object). +public interface PedidoRepositorio { + void salvar(Pedido pedido); + Optional buscarPorId(long id); + List buscarPorStatus(String status); +} diff --git a/src/com/lojaonline/servicos/ServicoPedido.java b/src/com/lojaonline/servicos/ServicoPedido.java new file mode 100644 index 0000000..e190bf8 --- /dev/null +++ b/src/com/lojaonline/servicos/ServicoPedido.java @@ -0,0 +1,48 @@ +package com.lojaonline.servicos; + +import com.lojaonline.envio.EnvioPort; +import com.lojaonline.pagamento.PagamentoPort; +import com.lojaonline.pedido.Pedido; +import com.lojaonline.pedido.StatusPedido; +import com.lojaonline.repositorio.PedidoRepositorio; + +// SRP: orquestra o fluxo; DIP: depende só de portas. +public class ServicoPedido { + private final PedidoRepositorio repo; + private final PagamentoPort pagamento; + private final EnvioPort envio; + + public ServicoPedido(PedidoRepositorio repo, PagamentoPort pagamento, EnvioPort envio) { + this.repo = repo; + this.pagamento = pagamento; + this.envio = envio; + } + + public long criarNovoPedido(Pedido pedido) { + repo.salvar(pedido); + System.out.println("Novo pedido criado! id=" + pedido.getId()); + return pedido.getId(); + } + + public void processarPedido(long id) { + var pedido = repo.buscarPorId(id).orElseThrow(() -> new IllegalArgumentException("Pedido não encontrado")); + if (pedido.getStatus() != StatusPedido.PENDENTE) { + throw new IllegalStateException("Apenas pedidos PENDENTES podem ser pagos."); + } + pagamento.pagar(pedido.calcularTotal()); + pedido.setStatus(StatusPedido.PAGO); + repo.salvar(pedido); + System.out.println("Pedido pago com sucesso!"); + } + + public void enviarPedido(long id) { + var pedido = repo.buscarPorId(id).orElseThrow(() -> new IllegalArgumentException("Pedido não encontrado")); + if (pedido.getStatus() != StatusPedido.PAGO) { + throw new IllegalStateException("Só é possível enviar pedidos pagos."); + } + envio.enviarPara(pedido.getEnderecoEntrega()); + pedido.setStatus(StatusPedido.ENVIADO); + repo.salvar(pedido); + System.out.println("Pedido enviado com sucesso!"); + } +} diff --git a/src/oopII.iml b/src/oopII.iml new file mode 100644 index 0000000..b107a2d --- /dev/null +++ b/src/oopII.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file