4

設計に関する質問があります。簡単な例で説明します。

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を1回だけ取得したいので、静的初期化ブロックを使用しています。

public class B {

//ここでURLを変更し、getJsonメソッドを呼び出します。A.setUrl()を呼び出すと、urlを設定する前に、静的初期化ブロックでA.getJson()メソッドが呼び出されます。最初にurlを設定してから、getJson()を呼び出すにはどうすればよいですか。

//is this a bad design?

}
4

3 に答える 3

2

はい、それは悪いデザインです:

  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また、アプリケーション全体に同時に1つのマップしかないことを強制するため、を取り除くことを検討してください。これは非常に柔軟性がありません。(方法については、Ajayの回答の2番目のコードサンプルを参照してください)

于 2012-08-06T20:21:18.037 に答える
2

これはうまくいくはずです。新しいメソッドを追加します。

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

単体テストが困難になるため、静的イニシャライザーは一般的に悪い考えです。

テスト可能なコードを書くためのMiskoHeveryのガイドをチェックしてください。

次のような操作を行うことで、デザインを作り直すことができます。

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

このようにして、単一責任の原則に従うことができます。

これで、両方のクラスもテスト可能になります。

于 2012-08-06T19:36:28.703 に答える
1

URLはどこに設定されていますか?コンストラクターで?もしそうなら、単にします

//Normal init stuff like set url here, followed by
if (! some check for if json is set) {
     setJson();
}
于 2012-08-06T19:27:10.083 に答える