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;
}
}