为何在类内部实例化自身?请解析State类及对应设计模式
解析State类的设计:为什么内部实例化自身?这是啥模式?
好问题!咱们一步步拆解这段C#代码的设计思路、目的和对应的模式:
一、为什么要在State类内部实例化自身?
核心原因是完全控制状态实例的创建,确保类型安全和状态的唯一性:
- 这个类的构造函数是
private的,外部代码根本没法直接new State(),所有实例都只能由类自己提供。 - 这样就能保证整个程序里只会存在你预先定义的这4个State实例,不会出现随意创建的无效状态(比如有人瞎写
new State("Invalid"))。 - 同时,每个静态属性对应的实例都是单例——首次访问时创建,之后一直复用同一个对象,避免不必要的内存开销。
二、代码逐行拆解
先贴出代码方便对照:
public class State { private State(String value) { Value = value; } public String Value { get; set; } public static State Open => new State("Open"); public static State Closed => new State("Closed"); public static State YourOpen => new State("YourOpen"); public static State YourClosed => new State("YourClosed"); }
- 私有构造函数:这是整个设计的关键,把实例创建权锁在类内部,外部无法随意生成State对象。
- 静态属性(表达式体写法):
public static State Open => new State("Open")这种写法是C#的语法糖,等价于一个只读的静态属性,首次访问时会创建对应的实例并缓存,之后每次访问都返回同一个对象。 - Value属性:这里虽然是
get; set;,但实际因为外部没法创建实例,只有内部的4个实例会被使用——不过更严谨的设计应该把它改成get; private set;,避免拿到实例后随意修改Value值,破坏状态的一致性。
三、这是不是用对象替代值的枚举?
没错!这就是用类实现的类型安全枚举,比C#原生的enum灵活太多:
- 原生
enum本质是整数的包装,只能关联单一的整数值;而这个State类可以轻松扩展——比如给每个状态加描述信息、添加状态转换的方法,甚至给不同状态赋予不同的行为逻辑。 - 类型安全更强:如果你的方法参数是
State类型,调用方只能传入预先定义好的4个实例,完全避免了传入无效字符串或枚举值的问题,编译器会直接帮你检查。 - 相比字符串常量,它是强类型的——不会出现把"Open"拼写成"Oepn"这种低级错误,也不用到处写魔法字符串。
四、对应的设计模式/术语
这就是类型安全枚举模式(Type-Safe Enum Pattern),也常被简称为枚举模式(Enum Pattern)。
这个模式的核心特征就是:
- 私有构造函数,禁止外部创建实例;
- 类内部提供静态的、预定义的实例集合;
- 每个实例代表一个固定的状态/选项,兼具枚举的简洁性和类的扩展性。
另外,它还结合了单例模式的思想——每个静态属性对应的实例都是单例,整个程序生命周期内只会存在一个State.Open、一个State.Closed等。
和原生enum相比,这个模式最大的优势是可扩展性:比如你可以给State类添加一个CanTransitionTo(State nextState)方法,让不同的实例返回不同的结果(比如Open可以转到Closed,但Closed不能转到Open),这是原生枚举根本做不到的。
内容的提问来源于stack exchange,提问作者Mike Murphy
相关产品推荐
相关产品推荐

