Getter与Setter设计疑问:当前定点浮点转换实现是否合理?
问题分析与优化方案
当前实现的不合理之处
- Getter存在副作用:Getter里直接修改私有字段
_value,违背了Getter的设计初衷——Getter应该是只读操作,不应该改变类的内部状态。外部调用者每次获取Value都可能触发值更新,会导致行为不可预测,比如连续调用Get可能返回不同结果,还会带来不必要的转换开销。 - 数据一致性风险:依赖
ValueUnchanged判断定点值是否变更,但如果外部修改定点值后这个标志没正确更新,Getter会返回旧的浮点值,导致内存中的定点值和类内缓存的浮点值不一致。 - 职责过于臃肿:Setter里塞了范围检查、反向转换、缓存设置等多个逻辑,违反单一职责原则,后续修改或维护时容易牵一发而动全身。
优化方案:拆分职责+明确同步逻辑
1. 重构Getter,移除副作用
让Getter只负责返回最新值,把定点值到浮点值的同步逻辑抽成独立方法。可以选择两种触发同步的方式:
- 每次Get时同步(适合定点值频繁变更的场景)
- 外部主动通知变更时同步(性能更优,推荐)
2. 封装定点值的访问
尽量避免外部直接操作内存中的定点值:
- 把定点值的读写都封装成
Parameter类的内部方法 - 如果必须允许外部修改,提供明确的
NotifyFixedPointValueChanged()方法,让外部修改后主动通知类内部同步,替代Getter被动检查的逻辑
3. 拆分Setter的职责
把范围校验、格式转换、缓存更新等逻辑拆成独立的私有方法,让Setter的逻辑更清晰,也方便单独测试。
优化后的示例代码
private TType _cachedFloatValue; // 封装定点值存储,避免外部直接访问 private int _fixedPointStorage; public TType Value { get { // 若需要每次Get都确保最新,调用同步方法;否则可移除,改用外部通知触发 SyncFixedPointToFloat(); return _cachedFloatValue; } set { if (value == null || _cachedFloatValue.Equals(value)) return; var validatedValue = ValidateValueRange(value); var convertedFixedPoint = ConvertFloatToFixedPoint(validatedValue); UpdateFixedPointStorage(convertedFixedPoint); _cachedFloatValue = validatedValue; } } // 同步定点值到浮点值的独立方法 private void SyncFixedPointToFloat() { var currentFixedValue = ReadFixedPointFromStorage(); var convertedFloat = ConvertFixedPointToFloat(currentFixedValue); if (!convertedFloat.Equals(_cachedFloatValue)) { _cachedFloatValue = convertedFloat; } } // 封装定点值读取 private int ReadFixedPointFromStorage() { // 实际读取内存中定点值的逻辑 return _fixedPointStorage; } // 封装定点值更新 private void UpdateFixedPointStorage(int value) { _fixedPointStorage = value; CacheFixedPointValue(value); // EEPROM同步可放到外部统一处理,或在这里触发 } // 拆分的独立职责方法 private TType ValidateValueRange(TType value) { // 范围校验逻辑 return value; } private int ConvertFloatToFixedPoint(TType value) { // 浮点转定点的转换逻辑 return default; } private TType ConvertFixedPointToFloat(int fixedValue) { // 定点转浮点的转换逻辑 return default; } private void CacheFixedPointValue(int value) { // 缓存定点值的逻辑 } // 外部修改定点值后,调用此方法通知同步 public void NotifyFixedPointValueChanged() { SyncFixedPointToFloat(); }
额外建议
- 优先禁止外部直接修改内存中的定点值,所有操作都通过
Parameter类的接口完成,从根源上避免数据不一致问题。 - 如果必须支持外部直接修改,可考虑用观察者模式:当定点值所在内存区域变更时,主动触发
Parameter类的同步逻辑,减少Getter的性能损耗。
内容的提问来源于stack exchange,提问作者stackMeUp
相关产品推荐
相关产品推荐

