1

在 OOP 和所有编程中,我知道一个明确的规则是一个方法应该只执行一个特定的任务,如果需要执行另一个任务,那么应该创建另一个方法。我的问题是这在我的情况下似乎毫无意义,因为它只是使用更多代码而不是 1 大方法。

这是我的代码可以构造的两种方式(一种遵循标准约定,另一种不保存代码)

场景 1(2 种方法)

增加统计方法

public void increaseStat(short value, string stat)
{
       switch (stat)
       {
           case "stamina":
               if (staminaCheck.Checked == true)
               {
                   stamina += value;
                   staminaText.Text = Convert.ToString(stamina);
               }
               staminaCheck.Checked = false;
               break;

//There are 5 other similar cases for different stats but to save time I removed them
       }

和递减统计方法

public void decreaseStat(short value, string stat)
{
       switch (stat)
       {
           case "stamina":
               if (staminaCheck.Checked == true)
               {
                   stamina -= value;
                   staminaText.Text = Convert.ToString(stamina);
               }
               staminaCheck.Checked = false;
               break;

//There are 5 other similar cases for different stats but to save time I removed them
       } 

如您所见,除了 1 个操作是 + 而不是 - 之外,代码完全相同。因此,为了惯例,我决定这样做,而不是将所有代码复制到另一种方法中

场景2(一种处理增加和减少的大方法)

public void alterStat(short value, string stat, bool operator)
{
       switch (stat)
       {
           case "stamina":
               if (staminaCheck.Checked == true)
               { 
                   if (Operator == true) stamina -= value;
                   else stamina += value

                   staminaText.Text = Convert.ToString(stamina);
               }
               staminaCheck.Checked = false;
               break;

//There are 5 other similar cases but to save time I removed them
       }

这样,我通过添加一个简单的 if 语句在每个案例中添加 2 行额外的行,但节省了大量正在复制的代码。

我只是希望您对这是否被视为良好的编程实践提出意见。

感谢您的时间。

4

4 回答 4

2

可以执行以下操作:

public void Change(string stat, bool decrease)
{
       switch (stat)
       {
           case "stamina":
               if (staminaCheck.Checked == true)
               {
                   if(decrease)
                      stamina -= value;
                   else
                      stamina += value;
                   staminaText.Text = Convert.ToString(stamina);
               }
               staminaCheck.Checked = false;
               break;

//There are 5 other similar cases for different stats but to save time I removed them
       }
}

因此,创建一个收费的方法来减少增加传递的值。它的作用是基于bool参数。

这将是您在第二种情况下所做的可能的“形状”之一,但解决方案略有不同。

于 2013-01-01T22:27:05.850 回答
2

在我看来,减少重复代码的好处显然远远超过关注点分离的规则,尤其是在代码维护方面。

类似的场景是使用一个Enum作为对象的状态标志。正确的 OOP 方法是将每个状态建模为状态层次结构中的单独类。后者的缺点是您必须编写代码来找出对象的状态,特别是如果您使用访问者模式(在使用 OOP 时应该这样做)。

如果涉及到类的接口,您提到的规则特别有用。如果(对于您的类的用户)更清楚的是拥有IncreaseStat()DecreaseStat()操​​作,而不是拥有一个 general ChangeStat(),那么没有人会阻止您实现一个private ChangeStat()方法,该方法由相应的public方法调用以增加和减少统计信息。这样您就可以同时获得两个优势:针对特定任务进行特定操作,而在内部没有重复代码。

于 2013-01-02T02:42:55.060 回答
1

最佳解决方案是,如果您可以保留两个世界的好东西,因为您需要它们两个。问题是您将公开的公共接口和内部实现(OOP 中的基本概念之一)分开。你怎么做呢?

您仍然可以拥有这两种方法,增加和减少方式,然后将公共代码重构为私有方法,每个增加和减少方法都使用适当的标志调用该方法。

public void increaseStat(short value, string stat){
    alterStat(value, stat, true);
}

public void decreaseStat(short value, string stat){
    alterStat(value, stat, false);
}


private void alterStat(short value, string stat, bool operator){
    // do the actual work here.
}

在设计类时,这是一个非常重要的模式。同样,这个想法是将您作为类接口公开的内容与您真正实现它的方式分开。每个人都应该为自己的目的服务,并且两者都可以一起工作。

于 2013-01-02T19:46:32.337 回答
0

由于 C# 具有 lambda,因此这些解决方案都不是理想的。相反,我会尝试将操作作为函数传递:

public void modStat(string stat, Func<short, short> op)
{
   switch (stat)
   {
       case "stamina":
           if (staminaCheck.Checked == true)
           { 
               stamina = op(stamina)

               staminaText.Text = Convert.ToString(stamina);
           }
           staminaCheck.Checked = false;
           break;

      // more cases
   }

这也比以前更普遍。理想情况下,我们也可以以相同的方式抽象属性,但这要困难得多(它需要一种称为lens的东西,而 C# 对 lens 没有太多支持)。

于 2013-01-01T22:37:44.723 回答