Java 如何重构这些方法?

Java 如何重构这些方法?,java,Java,我有4种方法基本相似,但我不知道如何重构它们 public String listWeatherConditions() { String retVal = ""; SimpleDateFormat formatter = new SimpleDateFormat("hh:mm a"); for(Map.Entry<String , ArrayList<Weather>> entry : this.weathers.entrySet())

我有4种方法基本相似,但我不知道如何重构它们

public String listWeatherConditions()
{
    String retVal = "";
    SimpleDateFormat formatter = new SimpleDateFormat("hh:mm a");
    for(Map.Entry<String , ArrayList<Weather>> entry : this.weathers.entrySet())
    {
        retVal = String.format("\n Data From %s \n", entry.getKey());
        retVal += String.format("displaying \tWeather Conditions hPa\n","");
        for (Weather element : this.weathers.get(entry.getKey()))
                {

                    retVal += String.format("%s\t\t%s\n",formatter.format(element.getCalculatedDate()) , element.getConditions() );
                }
    }

    retVal += "--------------------";
    return retVal;
}

public String listWind()
{
    String retVal = "";
    SimpleDateFormat formatter = new SimpleDateFormat("hh:mm a");
    for(Map.Entry<String , ArrayList<Weather>> entry : this.weathers.entrySet())
    {
        retVal = String.format("\n Data From %s \n", entry.getKey());
        retVal += String.format("displaying \tWind Direction\tWind SpeedKm/h\tWindDirDegrees\n","");
        for (Weather element : this.weathers.get(entry.getKey()))
                {

                    retVal += String.format("%s\t\t%s\t\t%s\t\t%d\n", formatter.format(element.getCalculatedDate()), element.getWindDirection() , element.getWindSpeedKmh() , element.getWindDirDegrees() );
                }
    }

    retVal += "--------------------";
    return retVal;

}
公共字符串listWeatherConditions()
{
字符串retVal=“”;
SimpleDataFormat格式化程序=新的SimpleDataFormat(“hh:mm a”);
对于(Map.Entry:this.weathers.entrySet())
{
retVal=String.format(“\n来自%s\n的数据”,entry.getKey());
retVal+=String.format(“显示\t其他条件hPa\n”,”);
for(Weather元素:this.weathers.get(entry.getKey()))
{
retVal+=String.format(“%s\t\t%s\n”,formatter.format(element.getCalculateDate()),element.getConditions());
}
}
retVal+=“-------------------”;
返回返回;
}
公共字符串listWind()
{
字符串retVal=“”;
SimpleDataFormat格式化程序=新的SimpleDataFormat(“hh:mm a”);
对于(Map.Entry:this.weathers.entrySet())
{
retVal=String.format(“\n来自%s\n的数据”,entry.getKey());
retVal+=String.format(“显示\tWind方向\tWind速度公里/小时\twinddirderegrees\n”,”);
for(Weather元素:this.weathers.get(entry.getKey()))
{
retVal+=String.format(“%s\t\t%s\t\t%s\t\t%d\n”,formatter.format(element.getCalculateDate()),element.getWindDirection(),element.getWindPeedKmh(),element.getWindDirDegrees());
}
}
retVal+=“-------------------”;
返回返回;
}

如何重构它们?

我认为这两种方法至少有两点不同:头和格式不同。在泛型方法中,只需传递字符串参数即可处理不同的头。第二个问题可以通过包含一个参数来解决,该参数指示如何格式化字符串,并且您可以在方法中相应地处理它

如果你想要一个真正通用的方法,你可以通过一个接口来实现。大概是这样的:

interface WeatherFormatter {
    String formatWeather(Weather weather);
}
listConditions("displaying \tWeather Conditions hPa\n", new WeatherFormatter() {
    String formatWeather(Weather weather) {
        return String.format("%s\t\t%s\n", formatter.format(weather.getCalculatedDate()), weather.getConditions());
    }
});
您的通用方法:

public String listConditions(String header, WeatherFormatter weatherFormatter) {
    String retVal = "";
    SimpleDateFormat formatter = new SimpleDateFormat("hh:mm a");
    for(Map.Entry<String , ArrayList<Weather>> entry : this.weathers.entrySet()) {
        retVal = String.format("\n Data From %s \n", entry.getKey());
        retVal += header;
        for (Weather element : this.weathers.get(entry.getKey())) {
            retVal += weatherFormatter.formatWeather(weather);
        }
    }
    retVal += "--------------------";
    return retVal;
}

还有一个想法:你可以把我的两个建议结合起来。您可以为方法创建一个参数,该参数不仅是一个接口,而是一个实现此接口的枚举。在枚举声明中,为每个常量实现
formatWeather()
方法。这将是一个非常面向对象的设计。

我认为这两种方法至少在两个方面有所不同:有不同的标题和格式。在泛型方法中,只需传递字符串参数即可处理不同的头。第二个问题可以通过包含一个参数来解决,该参数指示如何格式化字符串,并且您可以在方法中相应地处理它

如果你想要一个真正通用的方法,你可以通过一个接口来实现。大概是这样的:

interface WeatherFormatter {
    String formatWeather(Weather weather);
}
listConditions("displaying \tWeather Conditions hPa\n", new WeatherFormatter() {
    String formatWeather(Weather weather) {
        return String.format("%s\t\t%s\n", formatter.format(weather.getCalculatedDate()), weather.getConditions());
    }
});
您的通用方法:

public String listConditions(String header, WeatherFormatter weatherFormatter) {
    String retVal = "";
    SimpleDateFormat formatter = new SimpleDateFormat("hh:mm a");
    for(Map.Entry<String , ArrayList<Weather>> entry : this.weathers.entrySet()) {
        retVal = String.format("\n Data From %s \n", entry.getKey());
        retVal += header;
        for (Weather element : this.weathers.get(entry.getKey())) {
            retVal += weatherFormatter.formatWeather(weather);
        }
    }
    retVal += "--------------------";
    return retVal;
}

还有一个想法:你可以把我的两个建议结合起来。您可以为方法创建一个参数,该参数不仅是一个接口,而是一个实现此接口的枚举。在枚举声明中,为每个常量实现
formatWeather()
方法。这将是一个非常面向对象的设计。

如果我正确地阅读了您的代码,那么两种方法之间的唯一区别似乎是如何处理循环中的天气对象。在本例中,您只是附加字符串。也许值得考虑一种方法来执行循环,并让它将实际的“我该如何处理这个”委托给您传入的对象

例如,您可以创建一个接口来表示“做点什么”部分

并为您想要的每种输出类型执行一次

public class WindWorker implements WeatherWork {
   public String formatWeatherString(Weather weather) {
      return String.format("%s\t\t%s\n",formatter.format(weather.getCalculatedDate()) , weather.getConditions());
   }
}
然后,重新实现你的天气循环代码,以采取这些新的对象之一

public String listWind() {
   return formatWeather(new WindWorker());
}
formatWeather()将执行循环

public String formatWeather(WeatherWork worker) {
   String retVal = "";
   SimpleDateFormat formatter = new SimpleDateFormat("hh:mm a");
   for(Map.Entry<String , ArrayList<Weather>> entry : this.weathers.entrySet()) {
    retVal = String.format("\n Data From %s \n", entry.getKey());
    for (Weather element : this.weathers.get(entry.getKey())) {
         retVal += worker.formatWeatherString(element);
    }

   retVal += "--------------------";
   return retVal;
}
公共字符串格式天气(天气工作者){
字符串retVal=“”;
SimpleDataFormat格式化程序=新的SimpleDataFormat(“hh:mm a”);
对于(Map.Entry:this.weathers.entrySet()){
retVal=String.format(“\n来自%s\n的数据”,entry.getKey());
for(Weather元素:this.weathers.get(entry.getKey())){
retVal+=worker.formatWeatherString(元素);
}
retVal+=“-------------------”;
返回返回;
}

编辑:哦,我错过了标题。你明白了,你可以把它们放在WeatherWorker中。只需在接口中添加一个方法来返回标题并在实现类中实现它。

如果我正确阅读了你的代码,那么这两种方法之间的唯一区别似乎就是如何处理循环中的天气对象。在这里在这种情况下,您只是在附加字符串。可能值得考虑一种方法来执行循环,并让它将实际的“我该怎么处理这个”委托给您传入的对象

例如,您可以创建一个接口来表示“做点什么”部分

并为您想要的每种输出类型执行一次

public class WindWorker implements WeatherWork {
   public String formatWeatherString(Weather weather) {
      return String.format("%s\t\t%s\n",formatter.format(weather.getCalculatedDate()) , weather.getConditions());
   }
}
然后,重新实现你的天气循环代码,以采取这些新的对象之一

public String listWind() {
   return formatWeather(new WindWorker());
}
formatWeather()将执行循环

public String formatWeather(WeatherWork worker) {
   String retVal = "";
   SimpleDateFormat formatter = new SimpleDateFormat("hh:mm a");
   for(Map.Entry<String , ArrayList<Weather>> entry : this.weathers.entrySet()) {
    retVal = String.format("\n Data From %s \n", entry.getKey());
    for (Weather element : this.weathers.get(entry.getKey())) {
         retVal += worker.formatWeatherString(element);
    }

   retVal += "--------------------";
   return retVal;
}
公共字符串格式天气(天气工作者){
字符串retVal=“”;
SimpleDataFormat格式化程序=新的SimpleDataFormat(“hh:mm a”);
对于(Map.Entry:this.weathers.entrySet()){
retVal=String.format(“\n来自%s\n的数据”,entry.getKey());
for(Weather元素:this.weathers.get(entry.getKey())){
retVal+=worker.formatWeatherString(元素);
}
retVal+=“-------------------”;
返回返回;
}
编辑:哎呀,我错过了标题。你明白了,你可以把它们放在WeatherWorker中。只需在接口中添加一个方法来返回标题并在实现类中实现它。

建议:使用该模式动态定义格式化策略

public String listWeatherFeature(IFormatterStrategy formatStrategy){
    String retVal = "";
    for(Map.Entry<String , ArrayList<Weather>> entry : this.weathers.entrySet()){
        retVal = String.format("\n Data From %s \n", entry.getKey());
         for (Weather element : this.weathers.get(entry.getKey())){
           retVal += formatStrategy.formatElement(element);
        }
    }
    retVal += "--------------------";
    return retVal;
}

public interface IFormatterStrategy{
   String formatElement(Weather element);
}

public class WindFormatterStrategy implements IFormatter{
   String formatElement(Weather element){
      SimpleDateFormat formatter = new SimpleDateFormat("hh:mm a");
      return String.format("%s\t\t%s\t\t%s\t\t%d\n", formatter.format(element.getCalculatedDate()), element.getWindDirection() , element.getWindSpeedKmh() , element.getWindDirDegrees() );
   }
} 

public class WeatherFormatterStrategy implements IFormatter{
   String formatElement(Weather element){
      SimpleDateFormat formatter = new SimpleDateFormat("hh:mm a");
      return String.format("%s\t\t%s\n",formatter.format(element.getCalculatedDate()) , element.getConditions() );
   }
}

// Usage
// Wind:  
String result = String.format("displaying \tWeather Conditions hPa\n","");
result  += listWeatherFeature(new WeatherFormatterStrategy());
// Weather
String result = String.format("displaying \tWeather Conditions hPa\n","");
result += listWeatherFeature(new WindFormatterStrategy());
公共字符串列表WeatherFeature(IFormatterStrategy formatStrategy){
字符串retVal=“”;
对于(Map.Entry:this.weathers.entrySe