Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

Variação de Implementação

Pessoal implementei um pouco diferente. O que vcs acham?

package br.com.schimidtsolutions.estudo.descontos;

import com.google.common.collect.Lists;

public class CalculadoraDescontoTest {

    public static void main(final String[] args) {
        Desconto descontoMaisQueCincoItens = new DescontoParaMaisDeCincoItens();

        descontoMaisQueCincoItens.tendoComoProximoDescontoNaAvaliacao(new DescontoParaMaisDeQuinhentosReais())
             .tendoComoProximoDescontoNaAvaliacao(new SemDesconto()); // Agora totalmente opcional o Sem Desconto

        Item mesa = new Item("MESA", 250);
        Item mesa1 = new Item("MESA", 250);
        Item mesa2 = new Item("MESA", 250);
        Item mesa3 = new Item("MESA", 250);
        Item mesa4 = new Item("MESA", 250);
        Item cadeira = new Item("CADEIRA", 250);

        Orcamento orcamento = new Orcamento(Lists.newArrayList(mesa, mesa1, mesa2, mesa3, mesa4, cadeira));

        double calcularDesconto = descontoMaisQueCincoItens.calcularDesconto(orcamento);

        System.out.println(calcularDesconto);
    }
}

package br.com.schimidtsolutions.estudo.descontos;

import java.util.Objects;

public abstract class Desconto {
    private static final Desconto SEM_DESCONTO = new SemDesconto();
    private Desconto proximoDesconto = SEM_DESCONTO;

    abstract double calcularDesconto(Orcamento orcamento);

    final Desconto tendoComoProximoDescontoNaAvaliacao(final Desconto proximoDesconto) {
        Objects.requireNonNull(proximoDesconto);

        this.proximoDesconto = proximoDesconto;

        return proximoDesconto;
    }

    Desconto getProximoDesconto() {
        return proximoDesconto;
    }
}

package br.com.schimidtsolutions.estudo.descontos;

public class DescontoParaMaisDeQuinhentosReais extends Desconto {

    @Override
    public double calcularDesconto(final Orcamento orcamento) {

        if (orcamento.getValorTotal() > 500) {
            System.out.printf("Desconto para mais de quinhentos reais aplicado no valor de R$ %.2f!\n", orcamento.getValorTotal());
            return orcamento.getValorTotal() * 0.07;
        }

        return getProximoDesconto().calcularDesconto(orcamento);
    }
}

package br.com.schimidtsolutions.estudo.descontos;

public class DescontoParaMaisDeCincoItens extends Desconto {

    @Override
    public double calcularDesconto(final Orcamento orcamento) {

        if (orcamento.getQuantidadeItens() > 5) {
            System.out.printf("Desconto para mais de cinco itens aplicado no orçamento de %d itens!\n", orcamento.getQuantidadeItens());
            return orcamento.getValorTotal() * 0.1;
        }

        return getProximoDesconto().calcularDesconto(orcamento);
    }
}

package br.com.schimidtsolutions.estudo.descontos;

public class Item {
    private final String nome;
    private final double valor;

    public Item(final String nome, final double valor) {
        this.nome = nome;
        this.valor = valor;
    }

    public String getNome() {
        return nome;
    }

    public double getValor() {
        return valor;
    }
}

package br.com.schimidtsolutions.estudo.descontos;

import java.util.Collections;
import java.util.List;
import java.util.Objects;

public class Orcamento {
    private final List<Item> itens;
    private double valor;

    public Orcamento(final List<Item> itens) {
        Objects.requireNonNull(itens);

        this.itens = itens;
        recalcularValorTotal();
    }

    public List<Item> getItens() {
        return Collections.unmodifiableList(itens);
    }

    public void adicionarItem(final Item item) {
        itens.add(item);

        recalcularValorTotal();
    }

    public int getQuantidadeItens() {
        return itens.size();
    }

    public double getValorTotal() {
        return valor;
    }

    private void recalcularValorTotal() {
        valor = itens.stream().mapToDouble(Item::getValor).sum();
    }
}

package br.com.schimidtsolutions.estudo.descontos;

public class SemDesconto extends Desconto {

    @Override
    public double calcularDesconto(final Orcamento orcamento) {
        return 0;
    }
}
1 resposta
solução!

Oi Felipe, achei que ficou boa sim.. O uso da classe abstrata em vez da interface deixa o código um pouco mais acoplado, dado que uma mudança na implementação da mãe pode afetar a filha sem que ela, necessariamente, saiba.. Mas aí são pontos negativos da herança de classes em si...