#include <iostream>
#include <string>
using namespace std;
class Account;
// The 'State' abstract class
class State {
protected:
Account *account;
double balance; // 残高
double interest;
double lowerLimit;
double upperLimit;
string state_name;
public:
// Properties
Account* getAccount();
void setAccount(Account *value);
double getBalance() {
return balance;
}
void setBalance(double value) {
balance = value;
}
virtual void Deposit(double amount) = 0;
virtual void Withdraw(double amount) = 0;
virtual void PayInterest() = 0;
string GetName() {
return state_name;
}
};
// The 'Context' class
class Account {
private:
State *_state;
string _owner;
public:
// Constructor
Account(const string &owner);
// Destructor
virtual ~Account() {
delete _state;
}
// Properties
double getBalance() {
return _state->getBalance();
}
State* getState() {
return _state;
}
void setState(State *state) {
delete _state;
_state = state;
}
void Deposit(double amount) {
_state->Deposit(amount);
cout << "Deposited $" << amount << " ---" << endl;
cout << " Balance = $" << getBalance() << endl;
cout << " Status = " << getState()->GetName() << endl;
cout << endl;
}
void Withdraw(double amount) {
_state->Withdraw(amount);
cout << "Withdraw $" << amount << " ---" << endl;
cout << " Balance = $" << getBalance() << endl;
cout << " Status = " << getState()->GetName() << endl;
cout << endl;
}
void PayInterest() {
_state->PayInterest();
cout << "Interest Paid ---" << endl;
cout << " Balance = $" << getBalance() << endl;
cout << " Status = " << getState()->GetName() << endl;
cout << endl;
}
};
// A 'ConcreteState' class
// Red indicates that account is overdrawn
class RedState : public State {
private:
double _serviceFee;
public:
// Constructor
RedState(State *state) {
balance = state->getBalance();
account = state->getAccount();
Initialize();
}
private:
void Initialize() {
// Should come from a datasource
interest = 0.0;
lowerLimit = -100.0;
upperLimit = 0.0;
_serviceFee = 15.00;
state_name = "RedState";
}
public:
virtual void Deposit(double amount) {
balance += amount;
StateChangeCheck();
}
virtual void Withdraw(double amount) {
amount -= _serviceFee;
cout << "No funds available for withdrawal!" << endl;
}
virtual void PayInterest() {
// No interest is paid
}
private:
void StateChangeCheck();
};
// A 'ConcreteState' class
// Silver indicates a non-interest bearing state
class SilverState : public State {
public:
// Overloaded constructors
SilverState(State *state) {
balance = state->getBalance();
account = state->getAccount();
Initialize();
}
SilverState(double balance, Account *account) {
this->balance = balance;
this->account = account;
Initialize();
}
private:
void Initialize() {
// Should come from a datasource
interest = 0.0;
lowerLimit = 0.0;
upperLimit = 1000.0;
state_name = "SilverState";
}
public:
virtual void Deposit(double amount) {
balance += amount;
StateChangeCheck();
}
virtual void Withdraw(double amount) {
balance -= amount;
StateChangeCheck();
}
virtual void PayInterest() {
balance += interest * balance;
StateChangeCheck();
}
private:
void StateChangeCheck();
};
// A 'ConcreteState' class
// Gold indicates an interest bearing state
class GoldState : public State {
public:
// Overloaded constructors
GoldState(State *state) {
balance = state->getBalance();
account = state->getAccount();
Initialize();
}
GoldState(double balance, Account *account) {
this->balance = balance;
this->account = account;
Initialize();
}
private:
void Initialize() {
// Should come from a database
interest = 0.05;
lowerLimit = 1000.0;
upperLimit = 10000000.0;
state_name = "GoldState";
}
public:
virtual void Deposit(double amount) {
balance += amount;
StateChangeCheck();
}
virtual void Withdraw(double amount) {
balance -= amount;
StateChangeCheck();
}
void PayInterest() {
balance += interest * balance;
StateChangeCheck();
}
private:
void StateChangeCheck();
};
//// State ////
Account* State::getAccount() {
return account;
}
void State::setAccount(Account *value) {
account = value;
}
//// Account ////
Account::Account(const string &owner) {
// New accounts are 'Silver' by default
_owner = owner;
_state = new SilverState(0.0, this);
}
//// RedState ////
void RedState::StateChangeCheck() {
if (balance > upperLimit) {
account->setState(new SilverState(this));
}
}
//// SilverState ////
void SilverState::StateChangeCheck() {
if (balance < lowerLimit) {
account->setState(new RedState(this));
} else if (balance > upperLimit) {
account->setState(new GoldState(this));
}
}
//// GoldState ////
void GoldState::StateChangeCheck() {
if (balance < 0.0) {
account->setState(new RedState(this));
} else if (balance < lowerLimit) {
account->setState(new SilverState(this));
}
}
///////////
// Entry point into console application.
int main() {
// Open a new account
Account *account = new Account("Jim Johnson");
// Apply financial transactions
account->Deposit(500.0); // deposit: 預け入れ
account->Deposit(300.0);
account->Deposit(550.0);
account->PayInterest(); // interest: 利子
account->Withdraw(2000.00); // withdraw: 引き落とし
account->Withdraw(1100.00);
delete account;
return 0;
}