Já estudei o padrão State em algum outro momento e achei estranho utilizar o modificador protected
nos atributos da classe. Talvez essa abordagem tenha sido utilizada nos exemplos da aula para facilitar o entendimento, mas não seria mais interessante encapsular esses atributos em métodos?
Seguem os códigos alternativos que desenvolvi. Percebam que nas classes ContaPositiva
e ContaNegativa
optei por apenas calcular o valor de desconto e deixei a classe ContaBancaria
continuar calculando o saldo. Essa abordagem é mais coesa na opinião de vocês?
public interface ContaState {
void positivar(ContaBancaria conta);
void negativar(ContaBancaria conta);
double depositar(double valor);
double sacar(double valor);
}
/**
* Uma conta que está com saldo positivo, aceita saques
* e o banco deposita 98% do valor do depósito.
*/
public class ContaPositiva implements ContaState {
@Override
public void positivar(ContaBancaria conta) {
throw new RuntimeException("Conta já está positiva!");
}
@Override
public void negativar(ContaBancaria conta) {
conta.alterarEstado(new ContaNegativa());
}
@Override
public double depositar(double valor) {
return valor * 0.98;
}
@Override
public double sacar(double valor) {
return valor;
}
}
/**
* Uma conta que está negativo, por exemplo, não aceita saques e
* depositam apenas 95% do valor total de um depósito efetuado.
*/
public class ContaNegativa implements ContaState {
@Override
public void positivar(ContaBancaria conta) {
conta.alterarEstado(new ContaPositiva());
}
@Override
public void negativar(ContaBancaria conta) {
throw new RuntimeException("Conta já está negativa!");
}
@Override
public double depositar(double valor) {
return valor * 0.95;
}
@Override
public double sacar(double valor) {
throw new RuntimeException("Não é possível sacar quando saldo está negativo. Por favor, efetue um depósito!");
}
}
public class ContaBancaria {
private ContaState estado;
private double saldo;
public ContaBancaria() {
saldo = 0.0;
estado = new ContaPositiva();
}
public double getSaldo() {
return saldo;
}
public void depositar(double valor) {
double valorDeposito = estado.depositar(valor);
saldo += valorDeposito;
if (estado instanceof ContaNegativa && saldo > 0) {
estado.positivar(this);
}
}
public double sacar(double valor) {
double valorSacado = estado.sacar(valor);
saldo -= valorSacado;
if (estado instanceof ContaPositiva && saldo < 0) {
estado.negativar(this);
}
return this.getSaldo();
}
void alterarEstado(ContaState estado) {
this.estado = estado;
}
}