C#状态模式示例疑问:委托作用、账户初始化及状态判断
我来帮你理清这几个关于状态模式实现的疑问,结合你提供的C#代码逐一说明:
问题1:为什么具体状态类和上下文类要使用Action委托?
首先,这里的委托核心作用是解耦状态类与上下文类(Account)的依赖关系。如果直接让状态类持有Account的引用,状态类会和Account的具体实现绑定死——比如以后Account修改了属性或方法,状态类大概率也要跟着调整。
用Action委托的话,状态类完全不需要知道Account的内部细节,只需要明确“要执行某个操作”:
- 比如
Deposit方法里的addToBalance委托,只是告诉状态类“执行这个委托就能完成余额增加”,状态类不用关心余额存在Account的哪个属性里; - 而
OnUnfreeze委托是给冻结状态(你的示例代码里没贴Frozen类,但从Active的Freeze方法能推断出这个类的存在)准备的:当账户从冻结状态恢复到活跃状态时,触发这个委托执行特定逻辑(比如通知用户、记录操作日志),状态类不需要直接调用Account的方法,只需要执行委托即可。
这种方式完全符合依赖倒置原则——状态类依赖抽象(委托代表的操作),而非具体的Account类,让代码更灵活、更容易扩展。
问题2:如何正确初始化Account实例(初始状态为NotVerified)?
你尝试的代码Action initialState = () => { }; Account account= new Account(initialState);语法上是正确的,但需要明确构造函数参数的意义:这个Action是onUnfreeze(解冻回调),而非“初始状态”。
Account的构造函数已经默认把初始状态设置为NotVerified了(看代码里this.State = new NotVerified(onUnfreeze);),所以你只需要根据需求传入解冻时的回调即可:
- 如果不需要解冻时的额外操作,直接传空委托:
Account account = new Account(() => { }); - 如果需要在解冻时执行特定逻辑(比如打印提示日志):
Account account = new Account(() => Console.WriteLine("账户已完成解冻"));
问题3:如何判断Account当前的状态?
因为Account里的State属性是private的,外部无法直接访问。你可以通过两种方式来暴露当前状态:
方式1:添加公开属性获取状态类型名
在Account类里添加一个只读属性,返回当前状态的类型名称:
class Account { // ... 原有代码 ... public string CurrentStateName => State.GetType().Name; }
使用时直接读取account.CurrentStateName,就能得到类似"NotVerified"、"Active"、"Closed"这样的状态名称。
方式2:给状态接口添加强类型状态标识
更优雅的方式是给IAccountState接口添加一个属性,结合枚举实现强类型的状态标识:
// 先定义状态枚举 public enum AccountStateType { NotVerified, Active, Frozen, Closed } // 修改状态接口 interface IAccountState { AccountStateType StateType { get; } // ... 原有方法 ... } // 每个具体状态类实现这个属性 class NotVerified : IAccountState { public AccountStateType StateType => AccountStateType.NotVerified; // ... 原有代码 ... } class Active : IAccountState { public AccountStateType StateType => AccountStateType.Active; // ... 原有代码 ... } // 最后在Account类里添加公开属性 class Account { // ... 原有代码 ... public AccountStateType CurrentState => State.StateType; }
这种方式类型更安全,避免了字符串比较的潜在问题,也更符合面向对象的设计思路。
内容的提问来源于stack exchange,提问作者Eseosa Omoregie

