ATM
约 1634 字大约 5 分钟
2025-11-27
下面是一个完整的ATM逻辑,使用参与者模式进行开发
ATM状态机
class atm
{
messaging::receiver incoming;
messaging::sender bank;
messaging::sender interface_hardware;
void (atm::*state)();
std::string account;
unsigned withdrawal_amount;
std::string pin;
void process_withdrawal()
{
incoming.wait()
.handle<withdraw_ok>(
[&](withdraw_ok const& msg)
{
interface_hardware.send(
issue_money(withdrawal_amount));
bank.send(
withdrawal_processed(account,withdrawal_amount));
state=&atm::done_processing;
})
.handle<withdraw_denied>(
[&](withdraw_denied const& msg)
{
interface_hardware.send(display_insufficient_funds());
state=&atm::done_processing;
})
.handle<cancel_pressed>(
[&](cancel_pressed const& msg)
{
bank.send(
cancel_withdrawal(account,withdrawal_amount));
interface_hardware.send(
display_withdrawal_cancelled());
state=&atm::done_processing;
});
}
void process_balance()
{
incoming.wait()
.handle<balance>(
[&](balance const& msg)
{
interface_hardware.send(display_balance(msg.amount));
state=&atm::wait_for_action;
})
.handle<cancel_pressed>(
[&](cancel_pressed const& msg)
{
state=&atm::done_processing;
});
}
void wait_for_action()
{
interface_hardware.send(display_withdrawal_options());
incoming.wait()
.handle<withdraw_pressed>(
[&](withdraw_pressed const& msg)
{
withdrawal_amount=msg.amount;
bank.send(withdraw(account,msg.amount,incoming));
state=&atm::process_withdrawal;
})
.handle<balance_pressed>(
[&](balance_pressed const& msg)
{
bank.send(get_balance(account,incoming));
state=&atm::process_balance;
})
.handle<cancel_pressed>(
[&](cancel_pressed const& msg)
{
state=&atm::done_processing;
});
}
void verifying_pin()
{
incoming.wait()
.handle<pin_verified>(
[&](pin_verified const& msg)
{
state=&atm::wait_for_action;
})
.handle<pin_incorrect>(
[&](pin_incorrect const& msg)
{
interface_hardware.send(
display_pin_incorrect_message());
state=&atm::done_processing;
})
.handle<cancel_pressed>(
[&](cancel_pressed const& msg)
{
state=&atm::done_processing;
});
}
void getting_pin()
{
incoming.wait()
.handle<digit_pressed>(
[&](digit_pressed const& msg)
{
unsigned const pin_length=4;
pin+=msg.digit;
if(pin.length()==pin_length)
{
bank.send(verify_pin(account,pin,incoming));
state=&atm::verifying_pin;
}
})
.handle<clear_last_pressed>(
[&](clear_last_pressed const& msg)
{
if(!pin.empty())
{
pin.pop_back();
}
})
.handle<cancel_pressed>(
[&](cancel_pressed const& msg)
{
state=&atm::done_processing;
});
}
void waiting_for_card()
{
interface_hardware.send(display_enter_card());
incoming.wait()
.handle<card_inserted>(
[&](card_inserted const& msg)
{
account=msg.account;
pin="";
interface_hardware.send(display_enter_pin());
state=&atm::getting_pin;
});
}
void done_processing()
{
interface_hardware.send(eject_card());
state=&atm::waiting_for_card;
}
atm(atm const&)=delete;
atm& operator=(atm const&)=delete;
public:
atm(messaging::sender bank_,
messaging::sender interface_hardware_):
bank(bank_),interface_hardware(interface_hardware_)
{}
void done()
{
get_sender().send(messaging::close_queue());
}
void run()
{
state=&atm::waiting_for_card;
try
{
for(;;)
{
(this->*state)();
}
}
catch(messaging::close_queue const&)
{
}
}
messaging::sender get_sender()
{
return incoming;
}
};