2011-12-03 35 views
1

我有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; 

} 

我怎麼可以重構呢?

+0

我只算2種方法定義格式的策略。 –

+0

我在這裏只複製了其中的兩個,只是爲了方便 –

回答

4

我至少在兩點看到兩種方法之間的區別:你有不同的標題,你有不同的格式。在泛型方法中,可以通過傳遞String參數來簡單處理不同的頭文件。第二個問題可以通過包含一個參數來解決,該參數指示如何格式化字符串,並在相應的方法中處理該問題。

如果你想要一個真正通用的方法,你可以通過一個接口來完成。事情是這樣的:

interface WeatherFormatter { 
    String formatWeather(Weather weather); 
} 

您的泛型方法:

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; 
} 

而你打電話給你的通用方法是這樣的:

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()); 
    } 
}); 

還有一個想法:你可以在我的建議結合了。你爲方法創建一個參數,它不僅僅是一個接口,而是一個實現這個接口的枚舉。在你的枚舉聲明中,你爲每個常量實現你的formatWeather()方法。這將是一個非常面向對象的設計。

+0

+1。與我的想法完全一樣,但有更好更快的解釋。 –

+0

+1剛發佈了同樣的想法:D – GETah

+0

我需要一些關於如何實現你在這裏說的東西的幫助,這是我第一次重構這樣的東西,我真的不知道如何實現一個通用的循環然後獲得它的動態價值,我已經邀請你去盼望你回答它。 –

2

如果我正確讀取您的代碼,似乎這兩種方法之間的唯一區別就是如何處理循環中的Weather對象。在這種情況下,你只是附加字符串。可能值得考慮一種方法來完成循環,並讓它將實際的「我該怎麼做」委託給您傳遞的對象。

例如,您可以創建一個接口來表示「do一些」零件...

public Interface WeatherWork { 
    public String formatWeatherString(Weather weather); 
} 

併爲每種類型你想要的輸出,一旦實現它...

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; 
} 

編輯:哎呀,我錯過了頭。你明白了,你可以把它們放在WeatherWorker中。只需在接口中添加一個方法來返回頭並在實現類中實現它。

+1

+1與我的意見完全相同:)使用Lambda謂詞,這會更容易 – GETah

+1

@GETah只要我看到這個問題,我就會想到同樣的事情...... – Todd

0

建議:使用Strategy模式在飛行中

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());