c# - 如何正确实现状态模式?
问题描述
- 一个帐户可以有各种状态,例如 Frozen、Active、NotVerified、Closed。
- Account 可以执行以下操作:Deposit()、Withdraw()、HolderVerified()、Close()、Freeze()
- 这些操作的这些实施可能会因帐户的当前状态而异。
以下是我处理上述情况的方法。但是,如果我们遇到必须:
账户当前状态为冻结状态下入金,扣10%入金?
帐户
class Account
{
public decimal Balance { get; private set; }
private IAccountState State { get; set; }
public Account(Action onUnfreeze)
{
this.State = new NotVerified(onUnfreeze);
}
public void Deposit(decimal amount)
{
this.State = this.State.Deposit(() => { this.Balance += amount; });
}
public void Withdraw(decimal amount)
{
this.State = this.State.Withdraw(() => { this.Balance -= amount; });
}
public void HolderVerified()
{
this.State = this.State.HolderVerified();
}
public void Close()
{
this.State = this.State.Close();
}
public void Freeze()
{
this.State = this.State.Freeze();
}
}
IAccountState
interface IAccountState
{
IAccountState Deposit(Action addToBalance);
IAccountState Withdraw(Action substractFromBalance);
IAccountState Freeze();
IAccountState HolderVerified();
IAccountState Close();
}
IAccountState 的具体实现
积极的
class Active : IAccountState
{
private Action OnUnfreeze { get; }
public Active(Action onUnfreeze)
{
OnUnfreeze = onUnfreeze;
}
public IAccountState Deposit(Action addToBalance)
{
addToBalance();
return this;
}
public IAccountState Withdraw(Action substractFromBalance)
{
substractFromBalance();
return this;
}
public IAccountState HolderVerified() => this;
public IAccountState Freeze() => new Frozen(this.OnUnfreeze);
public IAccountState Close() => new Closed();
}
未验证
class NotVerified : IAccountState
{
public Action OnUnfreeze { get; }
public NotVerified(Action onUnfreeze)
{
this.OnUnfreeze = onUnfreeze;
}
public IAccountState Close() => new Closed();
public IAccountState Deposit(Action addToBalance)
{
addToBalance();
return this;
}
public IAccountState Freeze() => this;
public IAccountState HolderVerified() => new Active(this.OnUnfreeze);
public IAccountState Withdraw(Action substractFromBalance) => this;
}
当账户的当前状态为冻结时,当您必须扣除 10% 的存款时,您将如何处理?
我不确定如何修改 NotVerified 类中的 Deposit 方法以满足要求:
public IAccountState Deposit(Action addToBalance)
{
addToBalance();
return this;
}
解决方案
我会使用枚举而不是接口:
enum AccountState
{
NotVerified,
Active,
Frozen,
Closed
}
class Account
{
public decimal Balance { get; private set; }
// I assumed the bank would want to deposit the 10% to its own account
public decimal Fees { get; set; }
public AccountState state {get; private set; } = AccountState.NotVerified;
public Account() {}
public void Deposit(decimal amount) {
if (this.state == AccountState.Active)
this.Balance += amount;
else if (this.state == AccountState.Frozen)
{
this.Balance += amount * (decimal).9;
this.Fees += amount * (decimal).1;
}
}
public void Withdraw(decimal amount) {
if (this.state == AccountState.Active)
this.Balance -= amount;
}
public bool HolderVerified() {
return (this.state == AccountState.Active);
}
public void Close() {
this.state = AccountState.Closed;
}
public void Freeze() {
this.state = AccountState.Frozen;
}
}
推荐阅读
- c# - httprequestmessage.createresponse() 在 System.net.http 中不存在
- android - 在 Flutter 中按下后如何更改 IconButton 的图标
- python - 在 pdm 文件中搜索关键字并提取该关键字
- angular - 当函数返回新值时,如何更新 Angular 中的子组件?
- rust - 处理 rust 中泛型和非泛型类型的枚举返回
- python - 你如何用 Python 正确地从 NVIDIA 网站上抓取数据?
- list - 如何在 Flutter 的 PaginatedDataTable 中使用 DataRows 列表?
- python - Django:如何在 for 循环中正确地进行 bulk_update_or_create()
- jenkins - 如何将 Jenkins 秘密文件传递给 Groovy 脚本?
- vue.js - Vue 测试工具提示的消息