Padrão de Estado: Implementação de Sistema Bancário com Mudança de Comportamento

O Padrão de Estado é um padrão de design comportamental que permite a um objeto modificar sua ação com base em seu estado interno. Neste artigo, aplicamos esse padrão para simular uma conta bancária com três estados distnitos, determinados pelo saldo da conta. O objetivo é ilustrar como operações como depósito e saque podem desencadear trensições automáticas antre estados, mantendo o código modular e extensível.

Definição dos estados da conta bancária:

  • Estado Normal (Verde): Saldo ≥ 0. Permite depósitos e saques.
  • Estado Atrasado (Amarelo): Saldo < 0 e ≥ -1000. Permite depósitos e saques.
  • Estado Sobregirado (Vermelho): Saldo < -1000. Permite apenas depósitos, bloqueando saques.

Implementação em C++ utilizando o Padrão de Estado:


#include <iostream>
#include <string>

class ContaBancaria;

class EstadoConta {
public:
    ContaBancaria* conta;
    double saldo;
    std::string nomeEstado;

    virtual void verificarEstado() = 0;
    virtual void depositar(double valor) {
        std::cout << conta->getDono() << " realizou depósito de " << valor << std::endl;
        saldo += valor;
        verificarEstado();
        std::cout << "Saldo atual: " << saldo << std::endl;
        std::cout << "Estado atual: " << conta->getEstado()->nomeEstado << std::endl;
    }
    virtual void sacar(double valor) {
        std::cout << conta->getDono() << " realizou saque de " << valor << std::endl;
        saldo -= valor;
        verificarEstado();
        std::cout << "Saldo atual: " << saldo << std::endl;
        std::cout << "Estado atual: " << conta->getEstado()->nomeEstado << std::endl;
    }
};

class ContaBancaria {
private:
    EstadoConta* estado;
    std::string dono;

public:
    ContaBancaria(std::string nome, double saldoInicial);
    void setEstado(EstadoConta* novoEstado) {
        this->estado = novoEstado;
    }
    EstadoConta* getEstado() {
        return this->estado;
    }
    std::string getDono() {
        return this->dono;
    }
    void depositar(double valor) {
        estado->depositar(valor);
    }
    void sacar(double valor) {
        estado->sacar(valor);
    }
};

class EstadoVermelho : public EstadoConta {
public:
    EstadoVermelho(EstadoConta* estadoAnterior) {
        this->saldo = estadoAnterior->saldo;
        this->conta = estadoAnterior->conta;
        this->nomeEstado = "Sobregirado";
    }
    void sacar(double valor) override {
        std::cout << "Conta em estado sobregirado: saque não permitido!" << std::endl;
    }
    void verificarEstado() override;
};

class EstadoAmarelo : public EstadoConta {
public:
    EstadoAmarelo(EstadoConta* estadoAnterior) {
        this->saldo = estadoAnterior->saldo;
        this->conta = estadoAnterior->conta;
        this->nomeEstado = "Atrasado";
    }
    void verificarEstado() override;
};

class EstadoVerde : public EstadoConta {
public:
    EstadoVerde(double saldoInicial, ContaBancaria* conta) {
        this->saldo = saldoInicial;
        this->conta = conta;
        this->nomeEstado = "Normal";
    }
    EstadoVerde(EstadoConta* estadoAnterior) {
        this->conta = estadoAnterior->conta;
        this->saldo = estadoAnterior->saldo;
        this->nomeEstado = "Normal";
    }
    void verificarEstado() override {
        if (saldo >= -1000 && saldo < 0) {
            conta->setEstado(new EstadoAmarelo(this));
        } else if (saldo < -1000) {
            conta->setEstado(new EstadoVermelho(this));
        } else {
            conta->setEstado(new EstadoVerde(this));
        }
    }
};

void EstadoVermelho::verificarEstado() {
    if (saldo >= -1000 && saldo < 0) {
        conta->setEstado(new EstadoAmarelo(this));
    } else if (saldo < -1000) {
        conta->setEstado(new EstadoVermelho(this));
    } else {
        conta->setEstado(new EstadoVerde(this));
    }
}

void EstadoAmarelo::verificarEstado() {
    if (saldo >= -1000 && saldo < 0) {
        conta->setEstado(new EstadoAmarelo(this));
    } else if (saldo < -1000) {
        conta->setEstado(new EstadoVermelho(this));
    } else {
        conta->setEstado(new EstadoVerde(this));
    }
}

ContaBancaria::ContaBancaria(std::string nome, double saldoInicial) {
    this->dono = nome;
    this->estado = new EstadoVerde(saldoInicial, this);
    std::cout << "Conta criada para " << dono << " com saldo inicial: " << saldoInicial << std::endl;
    std::cout << "----------------------------------------" << std::endl;
}

int main() {
    ContaBancaria* conta = new ContaBancaria("Maria", 1000.0);
    conta->depositar(200.0);
    conta->sacar(400.0);
    conta->sacar(900.0);
    conta->sacar(1000.0);
    delete conta;
    return 0;
}
</string></iostream>

Implementação em Java:


package estado;

// Classe que representa a conta bancária
public class ContaBancaria {
    private EstadoConta estado;
    private String titular;

    public ContaBancaria(String titular, double saldoInicial) {
        this.titular = titular;
        this.estado = new EstadoVerde(saldoInicial, this);
        System.out.println("Saldo inicial: " + saldoInicial);
    }

    public void setEstado(EstadoConta novoEstado) {
        this.estado = novoEstado;
    }

    public void depositar(double valor) {
        estado.depositar(valor);
        System.out.println("Saldo: " + this.estado.saldo);
    }

    public void sacar(double valor) {
        estado.sacar(valor);
        System.out.println("Saldo: " + this.estado.saldo);
    }
}

// Classe abstrata para estados da conta
public abstract class EstadoConta {
    protected ContaBancaria conta;
    protected double saldo;

    public abstract void verificar();
    public abstract void depositar(double valor);
    public abstract void sacar(double valor);
}

// Estado normal (verde)
public class EstadoVerde extends EstadoConta {
    public EstadoVerde(double saldo, ContaBancaria conta) {
        this.saldo = saldo;
        this.conta = conta;
    }

    @Override
    public void verificar() {
        if (saldo > 0) {
            System.out.println("Estado: Normal");
            conta.setEstado(new EstadoVerde(saldo, conta));
        } else if (saldo <= 0 && saldo >= -1000) {
            System.out.println("Estado: Atrasado");
            conta.setEstado(new EstadoAmarelo(saldo, conta));
        } else {
            System.out.println("Estado: Sobregirado");
            conta.setEstado(new EstadoVermelho(saldo, conta));
        }
    }

    @Override
    public void depositar(double valor) {
        saldo += valor;
        verificar();
    }

    @Override
    public void sacar(double valor) {
        saldo -= valor;
        verificar();
    }
}

// Estado atrasado (amarelo)
public class EstadoAmarelo extends EstadoConta {
    public EstadoAmarelo(double saldo, ContaBancaria conta) {
        this.saldo = saldo;
        this.conta = conta;
    }

    @Override
    public void verificar() {
        if (saldo > 0) {
            System.out.println("Estado: Normal");
            conta.setEstado(new EstadoVerde(saldo, conta));
        } else if (saldo <= 0 && saldo >= -1000) {
            System.out.println("Estado: Atrasado");
            conta.setEstado(new EstadoAmarelo(saldo, conta));
        } else {
            System.out.println("Estado: Sobregirado");
            conta.setEstado(new EstadoVermelho(saldo, conta));
        }
    }

    @Override
    public void depositar(double valor) {
        saldo += valor;
        verificar();
    }

    @Override
    public void sacar(double valor) {
        saldo -= valor;
        verificar();
    }
}

// Estado sobregirado (vermelho)
public class EstadoVermelho extends EstadoConta {
    public EstadoVermelho(double saldo, ContaBancaria conta) {
        this.saldo = saldo;
        this.conta = conta;
    }

    @Override
    public void verificar() {
        if (saldo > 0) {
            System.out.println("Estado: Normal");
            conta.setEstado(new EstadoVerde(saldo, conta));
        } else if (saldo <= 0 && saldo >= -1000) {
            System.out.println("Estado: Atrasado");
            conta.setEstado(new EstadoAmarelo(saldo, conta));
        } else {
            System.out.println("Estado: Sobregirado");
            conta.setEstado(new EstadoVermelho(saldo, conta));
        }
    }

    @Override
    public void depositar(double valor) {
        saldo += valor;
        verificar();
    }

    @Override
    public void sacar(double valor) {
        System.out.println("Saque bloqueado: conta em estado sobregirado.");
    }
}

// Classe de teste
public class TesteConta {
    public static void main(String[] args) {
        ContaBancaria conta = new ContaBancaria("João", 500.0);
        conta.depositar(100.0);
        conta.sacar(700.0);
        conta.sacar(300.0);
        conta.depositar(500.0);
    }
}

Tags: state-pattern java cpp bank-account-simulation design-patterns

Publicado em 6-26 21:20