类方法实现:它应该更改类的成员变量还是接受参数?

时间:2010-07-21 07:26:58

标签: oop architecture

我想我会尝试通过2个代码段来解释我的问题:

// snippet 1
class FooBar
{
   private int value;

   public int DetermineSomeResult()
   {
       PerformSomeCalculationOnValue();
       PerformSomeMoreStuffOnValue();

       return value;
   }

   public int GetCachedValue()
    {
       return value;
    }
}

第一个实现基本上有对私有整数成员进行操作的方法。

这是第二个实现

// snippet 2
class FooBar2
{
    private int value;

    public int DetermineSomeResult()
    {
       int tempvalue =GetCachedValue();
       tempvalue =  PerformSomeCalculationOnValue(tempvalue);
       tempvalue = PeformMoreStuffOnValue(tempvalue);

       SetValue(tempvalue);
       return tempvalue;
    }

    public int GetCachedValue()
    {
       return value;
    }
}

对于第二个实现,在完成所有计算之前,不会对内部状态进行任何更改。设计明智哪一个更好?

我倾向于选择第二个,因为它更清晰,显示了依赖关系。但是,由于类本身已经存储了一个用于计算值的类成员,因此使用它似乎很愚蠢。

对此有何想法?

3 个答案:

答案 0 :(得分:1)

我认为您遇到的设计问题描述为 Command and state separation

简而言之,我建议DetermineSomeResult()应该只计算字段“value”的新值而不返回它,只有获得“值”的方法是通过GetCachedValue()

public void DetermineSomeResult()
{
   PerformSomeCalculationOnValue();
   PerformSomeMoreStuffOnValue();
   // consider "value" has already been set.
}

public int GetCachedValue()
{
   return value;
}

答案 1 :(得分:1)

通过使用带有参数的内部方法而不是将类成员变量视为该类的全局变量,您不仅可以更容易地对这些函数进行单元测试,而且还可以减少由于该成员变量被更改而引入错误的可能性不按顺序,特别是如果类有任何事件或工作线程驱动的行为。

所以我会选择第二个例子,而不是第一个例子。

修改的 此外,如果您的编程语言支持它们,您可以使用指向这些函数的给定变量类型的指针,以便它们成为(在C样式的伪代码中):

DoSomeWorkOn(pointerto int);

而不是

int newValue = DoSomeWorkOn(int oldValue);

答案 2 :(得分:1)

只要给出上面的代码,两者都可以。

但是,我想谈谈这里有一个微妙的问题。在第一种情况下,您的内部状态可能会处于不一致状态。如果PerformSomeMoreStuffOnValue方法在设置最终值的状态之前抛出异常,则会发生这种情况。第二种解决方案不会留在不存在的状态,不考虑可能正在发挥作用的其他事情。