如何基于C#枚举为LicenseState类实现对应构造方法?
实现方案与优化建议
基础实现:重载构造并添加合法性校验
通过重载构造方法,并在构造内部校验参数的合法性,确保不同状态使用对应的构造逻辑:
public enum LicenseStateType { Valid, Expiring, Expired } public class LicenseState { public LicenseStateType State { get; protected set; } public int DaysLeft { get; protected set; } // 仅用于Valid/Expired状态的构造 public LicenseState(LicenseStateType type) { if (type is not (LicenseStateType.Valid or LicenseStateType.Expired)) { throw new ArgumentException($"此构造仅支持{nameof(LicenseStateType.Valid)}或{nameof(LicenseStateType.Expired)}状态", nameof(type)); } State = type; DaysLeft = 0; // 非预警状态下剩余天数设为0,可根据需求调整 } // 仅用于Expiring状态的构造 public LicenseState(LicenseStateType type, int daysLeft) { if (type != LicenseStateType.Expiring) { throw new ArgumentException($"此构造仅支持{nameof(LicenseStateType.Expiring)}状态", nameof(type)); } if (daysLeft <= 0) { throw new ArgumentOutOfRangeException(nameof(daysLeft), "剩余天数必须大于0"); } State = type; DaysLeft = daysLeft; } }
这种方式直接满足需求,但调用方需要准确记住不同状态对应的构造方法,存在误用的可能性。
更优方案:静态工厂方法
使用语义化的静态工厂方法封装实例创建逻辑,让调用更直观、安全,避免参数组合错误:
public enum LicenseStateType { Valid, Expiring, Expired } public class LicenseState { public LicenseStateType State { get; } public int DaysLeft { get; } // 私有构造,强制所有实例通过工厂方法创建 private LicenseState(LicenseStateType state, int daysLeft) { State = state; DaysLeft = daysLeft; } public static LicenseState CreateValid() { return new LicenseState(LicenseStateType.Valid, 0); } public static LicenseState CreateExpired() { return new LicenseState(LicenseStateType.Expired, 0); } public static LicenseState CreateExpiring(int daysLeft) { if (daysLeft <= 0) { throw new ArgumentOutOfRangeException(nameof(daysLeft), "剩余天数必须大于0"); } return new LicenseState(LicenseStateType.Expiring, daysLeft); } }
方案优势:
- 调用直观:调用方无需关注构造参数,通过
CreateValid()、CreateExpired()、CreateExpiring(int)等语义化方法直接创建对应状态的实例,降低学习成本和误用概率 - 逻辑集中:所有状态创建的校验和规则都封装在工厂方法中,便于统一维护
- 扩展性强:后续新增状态或调整创建规则时,只需添加或修改工厂方法,无需修改构造逻辑
进阶扩展:状态模式(若需状态相关行为)
如果未来需要为不同许可证状态添加专属行为(比如不同状态下的验证逻辑、提示文案生成等),可以采用状态模式,为每个状态创建子类:
public abstract class LicenseState { public abstract LicenseStateType State { get; } public virtual int DaysLeft => 0; // 示例:状态专属行为 public abstract string GetStatusMessage(); } public class ValidLicenseState : LicenseState { public override LicenseStateType State => LicenseStateType.Valid; public override string GetStatusMessage() => "许可证状态有效"; } public class ExpiredLicenseState : LicenseState { public override LicenseStateType State => LicenseStateType.Expired; public override string GetStatusMessage() => "许可证已过期"; } public class ExpiringLicenseState : LicenseState { public override LicenseStateType State => LicenseStateType.Expiring; public override int DaysLeft { get; } public ExpiringLicenseState(int daysLeft) { if (daysLeft <= 0) { throw new ArgumentOutOfRangeException(nameof(daysLeft), "剩余天数必须大于0"); } DaysLeft = daysLeft; } public override string GetStatusMessage() => $"许可证将在{DaysLeft}天后过期"; }
这种方式将状态与行为绑定,适合状态需要承载业务逻辑的场景,代码的可读性和扩展性更强。
内容的提问来源于stack exchange,提问作者Antonio Argentieri
相关产品推荐
相关产品推荐

