unit conta;
interface
uses
SmartCL.System;
type
TWEstadoConta = class;
TWConta = class
private
_Estado : TWEstadoConta;
_NroConta : Integer;
_NomeCorrentista : String;
procedure VerificaStatus;
public
Constructor Create(ANomeCorrentista: String);
Destructor Destroy;override;
{ Operações }
procedure Depositar (AValor : Float);
procedure Sacar (AValor : Float);
procedure AplicarRendimento;
function ObtemSaldo : Float;
function ObtemNroConta : Integer;
function ObtemEstado : TWEstadoConta;
end;
TWEstadoConta = class
protected
_Saldo : Float;
_PorcRendim : Float;
_LimInf, _LimSup : Float;
_Conta : TWConta;
Constructor Create (AConta : TWConta);virtual;
procedure CopyFrom (AContaOrg : TWEstadoConta);virtual;
public
Destructor Destroy;override;
procedure Depositar (AValor : Float);virtual;abstract;
procedure Sacar (AValor : Float);virtual;abstract;
procedure AplicarRendimento;virtual;abstract;
end;
TWContaComum = class(TWEstadoConta)
protected
_TaxaServico : Float;
Constructor Create (AConta : TWConta);override;
public
procedure Depositar (AValor : Float);override;
procedure Sacar (AValor : Float);override;
procedure AplicarRendimento;override;
end;
TWContaDiferenciada = class(TWContaComum)
protected
_TaxaJuros : Float;
Constructor Create (AConta : TWConta);override;
public
procedure Depositar (AValor : Float);override;
procedure Sacar (AValor : Float);override;
procedure AplicarRendimento;override;
end;
TWContaOuro = class(TWEstadoConta)
protected
Constructor Create (AConta : TWConta);override;
public
procedure Depositar (AValor : Float);override;
procedure Sacar (AValor : Float);override;
procedure AplicarRendimento;override;
end;
implementation
{
C l a s s e T W C o n t a
}
Constructor TWConta.Create(ANomeCorrentista: String);
begin
_Estado := Nil;
_NroConta := Trunc (Now * 100.0);
_NomeCorrentista := ANomeCorrentista;
VerificaStatus ();
end;
Destructor TWConta.Destroy;
begin
// FreeAndNil (_Estado);
inherited;
end;
function TWConta.ObtemNroConta : Integer;
begin
Result := _NroConta;
end;
function TWConta.ObtemEstado : TWEstadoConta;
begin
Result := _Estado;
end;
procedure TWConta.VerificaStatus;
var lNovoEstado : TWEstadoConta;
begin
{ A conta é do tipo Comum por padrão }
if (_Estado = Nil) then begin
_Estado := TWContaComum.Create(Self);
Exit;
end;
{ Testa as variações de estado }
lNovoEstado := Nil;
if (_Estado._Saldo < _Estado._LimInf) then
begin
{ Rebaixa de COMUM para DIFERENCIADA }
if (_Estado is TWContaComum) then begin
// WriteLn('C - D');
lNovoEstado := TWContaDiferenciada.Create (Self);
end;
{ Rebaixa de OURO para COMUM }
if (_Estado is TWContaOuro) then begin
// WriteLn('o - c');
lNovoEstado := TWContaComum.Create (Self);
end;
end;
if (_Estado._Saldo > _Estado._LimSup) then
begin
{ Eleva de COMUM para OURO }
if (_Estado is TWContaComum) then begin
// WriteLn('c -> O');
lNovoEstado := TWContaOuro.Create (Self);
end;
{ Rebaixa de OURO para COMUM }
if (_Estado is TWContaOuro) then begin
// WriteLn('O -> c');
lNovoEstado := TWContaComum.Create (Self);
end;
{ Eleva de Diferenciada para Comum }
if (_Estado is TWContaDiferenciada) then begin
// WriteLn('D -> c');
lNovoEstado := TWContaComum.Create (Self);
end;
end;
{ Efetiva a troca de estado }
if (lNovoEstado <> Nil) then
begin
{ Copia dados relevantes do estado atual }
lNovoEstado.CopyFrom(_Estado);
{ Libera estado atual }
_Estado.Free;
{ Considera novo Estado }
_Estado := lNovoEstado;
end;
end;
function TWConta.ObtemSaldo : Float;
begin
Result := _Estado._Saldo;
end;
procedure TWConta.Depositar (AValor : Float);
begin
_Estado.Depositar(Avalor);
VerificaStatus ();
end;
procedure TWConta.Sacar (AValor : Float);
begin
_Estado.Sacar (AValor);
VerificaStatus ();
end;
procedure TWConta.AplicarRendimento;
begin
_Estado.AplicarRendimento ();
VerificaStatus ();
end;
{
C l a s s e T W E s t a d o C o n t a
}
Constructor TWEstadoConta.Create (AConta : TWConta);
begin
_Conta := AConta;
_Saldo := 0.0;
_PorcRendim := 0.0;
{ Valores de saldo que delimitam um estado }
_LimInf := 0.0;
_LimSup := 0.0;
end;
Destructor TWEstadoConta.Destroy;
begin
_Conta := Nil;
inherited;
end;
procedure TWEstadoConta.CopyFrom (AContaOrg : TWEstadoConta);
begin
{ Copia apenas as informações relevantes para a conta. As informações
que são específicas do estado, como a taxa de rendimento, devem permanacer
conforme configuradas no próprio estado. }
_Saldo := AContaOrg._Saldo;
_Conta := AContaOrg._Conta;
end;
{
C l a s s e T W C o n t a C o m u m
}
Constructor TWContaComum.Create (AConta : TWConta);
begin
// inherited;
_PorcRendim := 1.0; { Rendimento padrão : 1%}
_TaxaServico := 5.00; { Saques são cobrados }
{ Valores de saldo que delimitam um estado }
_LimInf := 100.00;
_LimSup := 999.99;
end;
procedure TWContaComum.Depositar (AValor : Float);
begin
_Saldo := _Saldo + AValor;
end;
procedure TWContaComum.Sacar (AValor : Float);
var lValorReal : Float;
begin
lValorReal := AValor + _TaxaServico;
_Saldo := _Saldo - lValorReal;
end;
procedure TWContaComum.AplicarRendimento;
begin
_Saldo := _Saldo + (_Saldo * _PorcRendim) / 100.0;
end;
{
C l a s s e T W C o n t a D i f e r e n c i a d a
}
Constructor TWContaDiferenciada.Create (AConta : TWConta);
begin
// inherited;
_PorcRendim := 0.0; { Sem rendimento }
_TaxaJuros := 1.00; { Taxa de juros sobre saques qdo a conta fica sem saldo }
_TaxaServico := 10.00; { Saques são cobrados }
{ Valores de saldo que delimitam um estado }
_LimInf := -100.00;
_LimSup := 99.99;
end;
procedure TWContaDiferenciada.Depositar (AValor : Float);
begin
_Saldo := _Saldo + AValor;
end;
procedure TWContaDiferenciada.Sacar (AValor : Float);
var lJuros, lValorReal : Float;
begin
lValorReal := AValor + _TaxaServico;
if (_Saldo - lValorReal) < _LimInf then
raise Exception.Create('Saque não pode ser efetivado. Conta sem saldo.');
lJuros := 0.0;
if (_Saldo - lValorReal) < 0.0 then
lJuros := (lValorReal - _Saldo) * _TaxaJuros / 100.0;
_Saldo := _Saldo - lValorReal - lJuros;
end;
procedure TWContaDiferenciada.AplicarRendimento;
begin
{ Esse tipo de conta não dá rendimentos }
end;
{
C l a s s e T W C o n t a O u r o
}
Constructor TWContaOuro.Create (AConta : TWConta);
begin
// inherited;
_PorcRendim := 2.00; { Rendimento Ouro : 2% }
{ Valores de saldo que delimitam um estado }
_LimInf := 1000.00;
_LimSup := 99999.99;
end;
procedure TWContaOuro.Depositar (AValor : Float);
begin
_Saldo := _Saldo + AValor;
end;
procedure TWContaOuro.Sacar (AValor : Float);
begin
_Saldo := _Saldo - AValor;
end;
procedure TWContaOuro.AplicarRendimento;
begin
_Saldo := _Saldo + (_Saldo * _PorcRendim) / 100.0;
end;
end.
|