簡體   English   中英

靜態初始化塊的設計問題

[英]Design issue on static initialization block

我有一個設計問題:讓我在簡單的例子中解釋一下:

Public class A()
{
public static HashMap map = new HashMap();
public static String url = "default";
static {
  getJson();
}

//url getters and setters are defined

public static getJson() {
//code which uses url to get json and populate hashmap
}
public string getresult(String key) {
//uses hashmap to send result.
}

我正在使用靜態初始化塊,因為我只想一次獲取json。

public class B {

//這里我要更改url並調用getJson方法。 如果我調用A.setUrl(),那么在設置url之前,將在靜態初始化塊中按原樣調用A.getJson()方法。我該如何先設置url然后再調用getJson()。

//is this a bad design?

}

我猜這應該工作。 添加新方法。

public static void getJson(String url) {
setUrl(url);
getJSon();
}

靜態初始化器通常是一個壞主意,因為單元測試變得困難。

查看Misko Hevery編寫可測試代碼的指南

您可以通過執行以下操作來重新設計:

public class A {
  //Add generics
  private Map map = new HashMap();
  public A(Map map){
    this.map = map;
  }
  public String getresult(String key) {
  //uses hashmap to send result.
  }

}

//Helper Class
public class URLToJSon() {
//Add private constructor
  public static Map convertUrlToJSon(String url) {
   //do the conversion and return a hashmap
  }
}

通過這種方式,我們可以遵循單一責任原則

現在,這兩個類也都可以測試。

是的,這是糟糕的設計:

  1. 在不修改A定義的情況下,無法自定義A從何處獲取數據。除其他外,這會阻止單元測試(因為如果網絡不可用,您可能不想使單元測試失敗...)。
  2. 如果初始化失敗(例如,因為遠程URL當前不可用),您將不容易捕獲該異常,因為您不知道哪個訪問觸發了加載。 您不能從靜態初始值設定項引發檢查異常。 您也不能重試初始化(所有后續訪問都會立即導致異常)。

如果必須通過靜態字段訪問A ,我建議:

public class A {
    private static Map<String, String> map;

    /** must be invoked before get is first called */
    public static void init(Map<String, String> newmap) {
        map = newmap;
    }

    public static String get(String key) {
        return map.get(key);
    }
}

這將使用數據的關注與獲取數據的關注區分開了,從而允許分別替換和測試每個數據。

還應考慮擺脫static ,因為它強制在整個應用程序中同時只有一個映射,這非常不靈活。 (有關方法,請參見Ajay答案中的第二個代碼示例)

URL在哪里設置? 在構造函數中? 如果是這樣,只需做

//Normal init stuff like set url here, followed by
if (! some check for if json is set) {
     setJson();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM