形から入る主義です。
id:yojikさんが書かれたコードをさらに写経。
一部、言語の制約とかで手を加えていますが、ほとんど直訳です。
中身はあとでもう一度考察する。
DCIアーキテクチャは、まだ読んでる途中。英語力のなさに悲しくなる。
勉強中につき突っ込み歓迎、大歓迎。
以下コード。
#include <iostream> #include <sstream> #include <string> #include <typeinfo> class Context; template<typename T> class Role { public: virtual ~Role() {} virtual Role& apply(T* t) = 0; virtual Role& on(Context* context) = 0; }; template<typename T> class Roles { public: Roles(T* target) : target_(target), role_(0) {} ~Roles() { delete role_; } template<typename R> R& as() { R* result = new R; delete role_; role_ = result; role_->apply(target_); return *result; } private: T* target_; Role<T>* role_; }; class Account { public: Account(const std::string& accountNumber) : role_(new Roles<Account>(this)), accountNumber_(accountNumber), balance_(10000) {} ~Account() { delete role_; } std::string accountNumber() const { return accountNumber_; } Roles<Account>& role() { return *role_; } int& balance() { return balance_; } const int& balance() const { return balance_; } private: Roles<Account>* role_; std::string accountNumber_; int balance_; }; class Context { public: virtual ~Context() {} virtual void show(const std::string& s) = 0; }; class TargetAccount : public Role<Account> { public: void deposit(int amount) { account_->balance() += amount; } TargetAccount& apply(Account* account) { account_ = account; return *this; } TargetAccount& on(Context* context) { context_ = context; return *this; } private: Account* account_; Context* context_; }; class SourceAccount : public Role<Account> { public: void transferTo(TargetAccount& target, int amount) { withdraw(amount); target.deposit(amount); } void withdraw(int amount) { account_->balance() -= amount; } SourceAccount& apply(Account* account) { account_ = account; return *this; } SourceAccount& on(Context* context) { context_ = context; return *this; } private: Account* account_; Context* context_; }; class AccountView : public Role<Account> { public: void show() { std::ostringstream oss; oss << account_->accountNumber() << " -> " << account_->balance(); context_->show(oss.str()); } AccountView& apply(Account* account) { account_ = account; return *this; } AccountView& on(Context* context) { context_ = context; return *this; } private: Account* account_; Context* context_; }; class TransferUsecase : public Context { public: void execute(const std::string& a, const std::string& b, int money) { Account* accountA = find(a); Account* accountB = find(b); SourceAccount& source = accountA->role().as<SourceAccount>().on(this); TargetAccount& target = accountB->role().as<TargetAccount>().on(this); source.transferTo(target, money); AccountView& fview = accountA->role().as<AccountView>().on(this); AccountView& tview = accountB->role().as<AccountView>().on(this); fview.show(); tview.show(); delete accountA; delete accountB; } void show(const std::string& s) { std::cout << s << std::endl; } Account* find(const std::string& accountNumber) { return new Account(accountNumber); } }; int main(int, char* []) { TransferUsecase transferUsecase; transferUsecase.execute("1111", "2222", 3000); return 0; }