Boa pergunta Igor!
GeradorDeNotaFiscal está acoplado à NotaFiscal, tendo a responsabilidade de controlar o ciclo de vida desta.
Eu faria da seguinte forma...
Colocaria o método de gerar nota fiscal dentro da classe Fatura passando como argumento as ações que devem ser realizadas após gerar a NotaFiscal, já que a NotaFiscal depende dos dados da Fatura para ser gerada. Também criaria uma interface Imposto com o método calcular(), depois criaria uma classe ImpostoSimples que implementa a interface Imposto. Esta interface seria o tipo da minha propriedade imposto, com isto, o calculo de imposto da fatura poderia ser alterado para qualquer tipo de imposto, alterando apenas o implementação do imposto que eu quero calcular:
import java.util.List;
public class Fatura {
private double valorMensal;
private String cliente;
private Imposto imposto;
public Fatura(double valorMensal, String cliente, Imposto imposto) {
this.valorMensal = valorMensal;
this.cliente = cliente;
this.imposto = imposto;
}
public double getValorMensal() {
return valorMensal;
}
public void setValorMensal(double valorMensal) {
this.valorMensal = valorMensal;
}
public String getCliente() {
return cliente;
}
public void setCliente(String cliente) {
this.cliente = cliente;
}
public Imposto getImposto() {
return imposto;
}
public void setImposto(Imposto imposto) {
this.imposto = imposto;
}
public NotaFiscal gerarNotaFiscal(List<AcaoPosNotaFiscal> acoesPosNotaFiscal) {
return new NotaFiscal(this.valorMensal, this.getValorImposto(), acoesPosNotaFiscal);
}
private double getValorImposto() {
return this.imposto.calcular(this.valorMensal);
}
}
public interface Imposto {
public double calcular(double valor);
}
public class ImpostoSimples implements Imposto {
public double calcular(double valor) {
return valor * 0.06;
}
}
Na classe NotaFiscal eu coloquei a lista com as ações que devem ser executadas após gerar a nota, como propriedade da classe. Também criei um método privado que executa estas ações e é chamado no construtor logo após settar os valores nas propriedades:
import java.util.List;
public class NotaFiscal {
private int id;
private double valorBruto;
private double impostos;
private final List<AcaoPosNotaFiscal> acoesPosNotaFiscal;
public NotaFiscal(int id, double valorBruto, double impostos, List<AcaoPosNotaFiscal> acoesPosNotaFiscal) {
this.id = id;
this.valorBruto = valorBruto;
this.impostos = impostos;
this.acoesPosNotaFiscal = acoesPosNotaFiscal;
executarAcoes();
}
public NotaFiscal(double valorBruto, double impostos, List<AcaoPosNotaFiscal> acoesPosNotaFiscal) {
this(0, valorBruto, impostos, acoesPosNotaFiscal);
executarAcoes();
}
private void executarAcoes() {
if (this.acoesPosNotaFiscal != null) {
for (AcaoPosNotaFiscal acao : this.acoesPosNotaFiscal) {
acao.acao(this);
}
}
}
public int getId() {
return id;
}
public double getValorBruto() {
return valorBruto;
}
public double getImpostos() {
return impostos;
}
public double getValorLiquido() {
return this.valorBruto - this.impostos;
}
}
Com isto a classe GeradorDeNotaFiscal, não seria mais necessária, pois seria resumido à isto:
public static void main(String[] args) {
Fatura fatura = new Fatura(2000.00, "Phelipe", new ImpostoSimples());
fatura.gerarNotaFiscal(null);
}