#include "bank.h"
int main()
{
Bank bank;
auto account1 = bank.OpenCheckingAccount();
auto account2 = bank.OpenSavingsAccount();
return 0;
}
#ifndef ILOGGER_H_
#define ILOGGER_H_
class ILogger {
public:
virtual ~ILogger() = default;
virtual void Log(const char* message) const = 0;
virtual void Log(const char* message, double value) const = 0;
};
#endif // ILOGGER_H_
#ifndef LOGGER_H_
#define LOGGER_H_
#include "ilogger.h"
class Logger : public ILogger {
public:
void Log(const char* message) const override;
void Log(const char* message, double value) const override;
};
#endif // LOGGER_H_
#ifndef ACCOUNT_H_
#define ACCOUNT_H_
#include "logger.h"
class Account {
protected:
const Logger logger_;
private:
static double interest_rate_;
double balance_{};
public:
virtual ~Account() = default;
static double GetInterestRate() noexcept;
static void SetInterestRate(double interest_rate) noexcept;
double GetBalance() const noexcept;
void Deposit(double amount) noexcept;
double Withdraw(double amount) noexcept;
virtual double CalculateInterest() noexcept;
};
#endif // ACCOUNT_H_
#ifndef BANK_H_
#define BANK_H_
#include <list>
#include <memory>
#include "logger.h"
class Account;
class Bank {
private:
std::list<std::shared_ptr<Account>> accounts_;
const Logger logger_;
public:
std::shared_ptr<Account> OpenSavingsAccount();
std::shared_ptr<Account> OpenCheckingAccount();
void PayInterest();
private:
std::shared_ptr<Account> OpenAccount(std::shared_ptr<Account> new_account);
};
#endif // BANK_H_
#ifndef CHECKINGACCOUNT_H_
#define CHECKINGACCOUNT_H_
#include "account.h"
class CheckingAccount : public Account {
private:
static double interest_rate_;
public:
static double GetInterestRate() noexcept;
static void SetInterestRate(double interest_rate) noexcept;
double CalculateInterest() noexcept override;
};
#endif // CHECKINGACCOUNT_H_
#define IOCCONTAINER_H_
#ifndef IOCCONTAINER_H_
#include <map>
#include <memory>
#include <mutex>
#include <string>
#include <typeinfo>
class IocContainer {
private:
std::map<std::string, std::shared_ptr<void> > objects_;
std::mutex objects_mutex_;
public:
~IocContainer() = default;
IocContainer(const IocContainer&) = delete;
IocContainer(IocContainer&&) = delete;
void operator=(const IocContainer&) = delete;
void operator=(IocContainer&&) = delete;
static IocContainer& Instance();
template <class T>
void Register(std::shared_ptr<T> t);
template <class T>
void Register(const std::string& id, std::shared_ptr<T> t);
template <class T>
std::shared_ptr<T> Resolve();
template <class T>
std::shared_ptr<T> Resolve(const std::string& id);
private:
IocContainer() = default;
};
template <class T>
void IocContainer::Register(std::shared_ptr<T> t)
{
const auto type_id = &typeid(T);
Register(type_id->name(), t);
}
template <class T>
void IocContainer::Register(const std::string& id, std::shared_ptr<T> t)
{
std::lock_guard<std::mutex> lock(objects_mutex_);
const auto iterator = objects_.find(id);
if (iterator != objects_.end()) {
throw std::runtime_error("Type already registered");
}
objects_[id] = t;
}
template <class T>
std::shared_ptr<T> IocContainer::Resolve()
{
const auto type_id = &typeid(T);
return Resolve<T>(type_id->name());
}
template <class T>
std::shared_ptr<T> IocContainer::Resolve(const std::string& id)
{
std::lock_guard<std::mutex> lock(objects_mutex_);
const auto iterator = objects_.find(id);
if (iterator != objects_.end()) {
return std::static_pointer_cast<T>(iterator->second);
}
throw std::runtime_error("Could not locate type");
}
#endif // IOCCONTAINER_H_
#ifndef SAVINGSACCOUNT_H_
#define SAVINGSACCOUNT_H_
#include "account.h"
class SavingsAccount : public Account {
private:
static double interest_rate_;
public:
static double GetInterestRate() noexcept;
static void SetInterestRate(double interest_rate) noexcept;
double CalculateInterest() noexcept override;
};
#endif // SAVINGSACCOUNT_H_
#include "logger.h"
void Logger::Log(const char* message) const { throw "Not Implemented"; }
void Logger::Log(const char* message, const double value) const
{
throw "Not Implemented";
}
#include "account.h"
double Account::interest_rate_{};
double Account::GetInterestRate() noexcept { return interest_rate_; }
void Account::SetInterestRate(const double interest_rate) noexcept
{
interest_rate_ = interest_rate;
}
double Account::GetBalance() const noexcept { return balance_; }
void Account::Deposit(const double amount) noexcept
{
balance_ += amount;
logger_.Log("Deposit, balance: ", balance_);
}
double Account::Withdraw(const double amount) noexcept
{
balance_ -= amount;
logger_.Log("Withdraw, balance: ", balance_);
return amount;
}
double Account::CalculateInterest() noexcept { return 0.0; }
#include "bank.h"
#include <ctime>
#include "checkingaccount.h"
#include "savingsaccount.h"
std::shared_ptr<Account> Bank::OpenSavingsAccount()
{
const auto account = std::make_shared<SavingsAccount>();
return OpenAccount(account);
}
std::shared_ptr<Account> Bank::OpenCheckingAccount()
{
const auto account = std::make_shared<CheckingAccount>();
return OpenAccount(account);
}
std::shared_ptr<Account> Bank::OpenAccount(std::shared_ptr<Account> new_account)
{
accounts_.push_back(new_account);
logger_.Log("Create account, number of accounts: ", accounts_.size());
return new_account;
}
void Bank::PayInterest()
{
for (auto& account : accounts_) {
const auto interest = account->CalculateInterest();
account->Deposit(interest);
}
logger_.Log("Interest paid on: ");
time_t current_time;
time(¤t_time);
const auto time_string = ctime(¤t_time);
if (time_string != nullptr) {
logger_.Log(&time_string[0]);
}
}
#include "checkingaccount.h"
#include "logger.h"
double CheckingAccount::interest_rate_{};
double CheckingAccount::GetInterestRate() noexcept { return interest_rate_; }
void CheckingAccount::SetInterestRate(const double interest_rate) noexcept
{
interest_rate_ = interest_rate;
}
double CheckingAccount::CalculateInterest() noexcept
{
const auto interest = GetBalance() * GetInterestRate();
logger_.Log("Calculate interest, amount: ", interest);
return interest;
}
#include "savingsaccount.h"
#include "logger.h"
double SavingsAccount::interest_rate_{};
double SavingsAccount::GetInterestRate() noexcept { return interest_rate_; }
void SavingsAccount::SetInterestRate(const double interest_rate) noexcept
{
interest_rate_ = interest_rate;
}
double SavingsAccount::CalculateInterest() noexcept
{
const auto interest = GetBalance() * GetInterestRate();
logger_.Log("Calculate interest, amount: ", interest);
return interest;
}