Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

Implementação com encapsulamento

Fiz uma implementação um pouco diferente. Gostaria que vcs opinassem.

package br.com.schimidtsolutions.estudo.solid.encapsulamento;

import com.google.common.collect.Lists;

import br.com.schimidtsolutions.estudo.solid.encapsulamento.CartaoDeCredito.TipoBandeira;

public class Programa {

    public static void main(final String[] args) {
        Fatura fatura = new Fatura("Fulano da Silva", 350);

        Lists.newArrayList(new Pagamento(new Boleto(50)), new Pagamento(new CartaoDeCredito(150, TipoBandeira.MASTERCARD)), new Pagamento(new Boleto(150)))
            .forEach(p -> fatura.pagar(p));

        System.out.println(fatura.isPago());
    }
}

package br.com.schimidtsolutions.estudo.solid.encapsulamento;

public interface Pagavel {

    MeioDePagamento getMeioPagamento();

    double getValor();
}

package br.com.schimidtsolutions.estudo.solid.encapsulamento;

public class Boleto implements Pagavel {
    private final double valor;

    public Boleto(final double valor) {
        this.valor = valor;
    }

    @Override
    public double getValor() {
        return valor;
    }

    @Override
    public MeioDePagamento getMeioPagamento() {
        return MeioDePagamento.BOLETO;
    }
}

package br.com.schimidtsolutions.estudo.solid.encapsulamento;

public class CartaoDeCredito implements Pagavel {
    private final double valor;
    private final TipoBandeira tipoBandeira;

    public CartaoDeCredito(final double valor, final TipoBandeira tipoBandeira) {
        this.valor = valor;
        this.tipoBandeira = tipoBandeira;
    }

    @Override
    public double getValor() {
        return valor;
    }

    public TipoBandeira getTipoBandeira() {
        return tipoBandeira;
    }

    @Override
    public MeioDePagamento getMeioPagamento() {
        return MeioDePagamento.BOLETO;
    }

    public enum TipoBandeira {
        VISA, MASTERCARD;
    }
}

package br.com.schimidtsolutions.estudo.solid.encapsulamento;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Fatura {
    private final String cliente;
    private final double valor;
    private final List<Pagamento> pagamentos;
    private boolean pago;

    public Fatura(final String cliente, final double valor) {
        this.cliente = cliente;
        this.valor = valor;
        pagamentos = new ArrayList<>();
        pago = false;
    }

    public String getCliente() {
        return cliente;
    }

    public double getValor() {
        return valor;
    }

    public List<Pagamento> getPagamentos() {
        return Collections.unmodifiableList(pagamentos);
    }

    public boolean isPago() {
        return pago;
    }

    public void pagar(final Pagamento pagamento) {
        pagamentos.add(pagamento);

        setarFaturaComoPagaDependendoDoTotalPago();
    }

    private void setarFaturaComoPagaDependendoDoTotalPago() {
        double totalPago = pagamentos.stream().mapToDouble(Pagamento::getValor).sum();

        if (totalPago >= valor) {
            pago = true;
        }
    }
}

package br.com.schimidtsolutions.estudo.solid.encapsulamento;

public enum MeioDePagamento {
    BOLETO, CARTAO

}

package br.com.schimidtsolutions.estudo.solid.encapsulamento;

public class Pagamento {
    private final double valor;
    private final MeioDePagamento forma;

    public Pagamento(final Pagavel pagavel) {
        valor = pagavel.getValor();
        forma = pagavel.getMeioPagamento();
    }

    public double getValor() {
        return valor;
    }

    public MeioDePagamento getForma() {
        return forma;
    }

    @Override
    public boolean equals(final Object obj) {
        if (!(obj instanceof Pagamento)) {
            return false;
        }
        Pagamento outro = (Pagamento) obj;
        if (forma != outro.forma || Double.doubleToLongBits(valor) != Double.doubleToLongBits(outro.valor)) {
            return false;
        }

        return true;
    }

}
3 respostas

Eu fiquei achando que a classe Pagamento meio que sobrou.. só a interface Pagavel já era suficiente.. dado que Pagamento só delega para a implementação da interface.

Gostei da dica, realmente ela estava sobrando mesmo. O resultado ficou assim.

package br.com.schimidtsolutions.estudo.solid.encapsulamento;

import com.google.common.collect.Lists;

import br.com.schimidtsolutions.estudo.solid.encapsulamento.CartaoDeCredito.TipoBandeira;

public class Programa {

    public static void main(final String[] args) {
        Fatura fatura = new Fatura("Fulano da Silva", 350);

        Lists.newArrayList(new Boleto(50), new CartaoDeCredito(150, TipoBandeira.MASTERCARD), new Boleto(150))
            .forEach(p -> fatura.pagar(p));

        System.out.println(fatura.isPago());
    }
}

package br.com.schimidtsolutions.estudo.solid.encapsulamento;

public class Boleto implements Pagavel {
    private final double valor;

    public Boleto(final double valor) {
        this.valor = valor;
    }

    @Override
    public double getValor() {
        return valor;
    }

    @Override
    public MeioDePagamento getMeioPagamento() {
        return MeioDePagamento.BOLETO;
    }
}

package br.com.schimidtsolutions.estudo.solid.encapsulamento;

public class CartaoDeCredito implements Pagavel {
    private final double valor;
    private final TipoBandeira tipoBandeira;

    public CartaoDeCredito(final double valor, final TipoBandeira tipoBandeira) {
        this.valor = valor;
        this.tipoBandeira = tipoBandeira;
    }

    @Override
    public double getValor() {
        return valor;
    }

    public TipoBandeira getTipoBandeira() {
        return tipoBandeira;
    }

    @Override
    public MeioDePagamento getMeioPagamento() {
        return MeioDePagamento.BOLETO;
    }

    public enum TipoBandeira {
        VISA, MASTERCARD;
    }
}

package br.com.schimidtsolutions.estudo.solid.encapsulamento;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Fatura {
    private final String cliente;
    private final double valor;
    private final List<Pagavel> pagamentos;
    private boolean pago;

    public Fatura(final String cliente, final double valor) {
        this.cliente = cliente;
        this.valor = valor;
        pagamentos = new ArrayList<>();
        pago = false;
    }

    public String getCliente() {
        return cliente;
    }

    public double getValor() {
        return valor;
    }

    public List<Pagavel> getPagamentos() {
        return Collections.unmodifiableList(pagamentos);
    }

    public boolean isPago() {
        return pago;
    }

    public void pagar(final Pagavel pagamento) {
        pagamentos.add(pagamento);

        setarFaturaComoPagaDependendoDoTotalPago();
    }

    private void setarFaturaComoPagaDependendoDoTotalPago() {
        double totalPago = pagamentos.stream().mapToDouble(Pagavel::getValor).sum();

        if (totalPago >= valor) {
            pago = true;
        }
    }
}

package br.com.schimidtsolutions.estudo.solid.encapsulamento;

public enum MeioDePagamento {
    BOLETO, CARTAO

}

package br.com.schimidtsolutions.estudo.solid.encapsulamento;

public interface Pagavel {

    MeioDePagamento getMeioPagamento();

    double getValor();
}
solução!

Boa Felipe, é isso aí! Desenvolver, muitas vezes tem disso.. vc vai refatorando até achar uma versão que fique boa o suficiente para o seu objetivo.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software