我应该为简单的switch语句使用多态性吗?

hxzsmxv2  于 2021-06-29  发布在  Java
关注(0)|答案(4)|浏览(370)

我是清理代码/重构的新手,我学会了避免像下面这样的长switch语句。我发现多态性是缩短复杂switch语句的有用技术。对于这个简单的switch语句,多态性是个好主意吗?

String periodValue;
int numberOfDataPoints;

getNumberOfDataPoints(String selectedGraphType) {
    switch (selectedGraphType) {
      case "1D": 
        {
          periodValue = "300";
          numberOfDataPoints = 289; 
        }
        break;
      case "5D": 
        {
          periodValue = "1800";
          numberOfDataPoints = 241;
        }
        break;
      case "1M": 
        {
          periodValue = "86400";
          numberOfDataPoints = 31;
        }
        break;
      case "1Y": 
        {
          periodValue = "259200";
          numberOfDataPoints = 123;
        }
        break;
  }

}

7tofc5zh

7tofc5zh1#

该代码最大的问题是缺乏类型安全性。此方法只能使用4个特定字符串,但可以接受任何字符串,而不会向其调用方提供接受哪些字符串的任何线索,也不会在调用方提供错误字符串时向其提供任何反馈。
一种改进的方法是改用枚举。这还允许您在枚举本身中存储有关值的其他数据:

public enum GraphType {
  day(300),
  week(1800),
  month(86400),
  year(259200);

  public final int periodValue;

  GraphType(int periodValue) {
    this.periodValue = periodValue;
  }
}

然后,计算数据点数量的方法可以变成:

getDataPoints(GraphType selectedGraphType) {
  int period = selectedGraphType.periodValue;
  // find datapoints depending on period
}
f2uvfpb9

f2uvfpb92#

我会这样写。

public enum GraphType {
  GT_1D(300, 289),
  GT_5D(1800, 241),
  GT_1M(86400, 31),
  GT_1Y(259200, 123);

  public final int periodValue;
  public final int numberOfDataPoints;

  GraphType(int periodValue, int numberOfDataPoints) {
    this.periodValue = periodValue;
    this.numberOfDataPoints = numberOfDataPoints;
  }
}

或者,如果periodvalue和numberofdatapoints后面隐藏了一些公式,我会在构造函数或方法中编写该公式。

dfty9e19

dfty9e193#

也许这将帮助您开始创建一个基图类,所有其他图形类型都可以扩展它。以及基于传入的给定字符串生成图形对象的工厂类。

public class Graph
{
    public String periodValue;
    public int dataPoints;

    public Graph()
    {
        periodValue = "0";
        dataPoints = 0;
    }

    public void setPeriodValue(String newValue)
    {
        periodValue = newValue;
    }

    public void setDataPoints(int newDataPoints)
    {
        dataPoints = newDataPoints;
    }

    public String getPeriodValue()
    {
        return periodValue;
    }

    public int getDataPoints()
    {
        return dataPoints;
    }
}

public class OneDayGraph extends Graph
{
    public OneDayGraph()
    {
        periodValue = "300";
        dataPoints = 289;
    }
}

//add more Graph classes that extend your base class, Graph

public class GraphFactory
{
    public Graph createGraph(String typeOfGraph)
    {
        switch (typeOfGraph)
        {
            case "1D": 
            {
                return new OneDayGraph();
            }
            //add more cases for other graph types...
            default:
            {
                System.out.println("No known string to Graph Class for " + typeOfGraph);
                break;
            }
        }

        return new Graph();
    }
}

然后您可以创建一个工厂对象,并为它指定特定的字符串来创建所需的图形对象

GraphFactory factory = new GraphFactory();
Graph oneDay = factory.createGraph("1D");
System.out.println("The periodValue is " + oneDay.getPeriodValue());
System.out.println("The dataPoints is " + oneDay.getDataPoints());
kxxlusnw

kxxlusnw4#

您不需要多态性,只需使用一个结合了这两个值的类和一个Map就可以省略switch语句。

public class GraphType {
   // made the fields public final and omitted the getters for simplicity.
   // add getters if needed

   public final int periodValue;
   public final int numberOfDataPoints;

   GraphType(int periodValue, int numberOfDataPoints) {
      this.periodValue = periodValue;
      this.numberOfDataPoints = numberOfDataPoints;
   }

}

然后建立Map

Map<String, GraphType> graphTypeByName = new HashMap<>();

graphTypeByName.put("1D",new GraphType(300, 289));
graphTypeByName.put("5D",new GraphType(1800, 241));
graphTypeByName.put("1M",new GraphType(86400, 31);
graphTypeByName.put("1Y",new GraphType(259200, 123);

使用Map

public GraphType getNumberOfDataPoints(String selectedGraphType) {
    GraphType graphType = graphTypeByName.get(selectedGraphType);

    if(graphType == null) {
       // handle graphType not registered. Default value or exception ?
    }

    return graphType;
}

此方法比使用枚举更灵活。默认情况也更容易测试。我认为 GraphType 不是枚举。枚举是一组不太可能更改的固定名称,如norh、south、east、west或hour、minutes、seconds。
如果你想确保 GraphType 如果您希望存在并且不能示例化其他对象,请实现如下注册表:

public class GraphTypeRegistry {

    public class GraphType {
       public final int periodValue;
       public final int numberOfDataPoints;

       private GraphType(int periodValue, int numberOfDataPoints) {
           this.periodValue = periodValue;
           this.numberOfDataPoints = numberOfDataPoints;
       }
   }

   private Map<String, GraphType> graphTypeByName = new HashMap<>();

   public GraphTypeRegistry(){
      graphTypeByName.put("1D",new GraphType(300, 289));
      graphTypeByName.put("5D",new GraphType(1800, 241));
      graphTypeByName.put("1M",new GraphType(86400, 31);
      graphTypeByName.put("1Y",new GraphType(259200, 123);
   }

   public GraphType getGraphType(String graphTypeName) {
      GraphType graphType = graphTypeByName.get(graphTypeName);

      if(graphType == null) {
         // handle graphType not registered. Default value or exception ?
      }

      return graphType;
  }
}

相关问题