53

コードのリファクタリングと if else ステートメントの回避に関する多くのトピックを読みました。実際、私は多くの if - else 条件を使用しているクラスを持っています。

詳細: プル パーサーを使用しており、soap 応答の各行で、関心のあるタグがあるかどうかを確認し、そうでない場合は別のタグなどを確認します。

 if(eventType == XmlPullParser.START_TAG) {
            soapResponse= xpp.getName().toString();
            
            if (soapResponse.equals("EditorialOffice")){  
                eventType = xpp.next();
                if (xpp.getText()!=null){
                editorialOffice += xpp.getText();
                }
            }   
            else if (soapResponse.equals("EditorialBoard")){  
                eventType = xpp.next();
                if (xpp.getText()!=null){
                editorialBoard += xpp.getText();
                }
            }
            else if (soapResponse.equals("AdvisoryBoard")){  
                eventType = xpp.next();
                if (xpp.getText()!=null){
                advisoryBoard += xpp.getText();
                }
            }   
        }
        eventType = xpp.next();
     }

今、if else条件の代わりに何か他のものを使いたいのですが、何がわかりません。

例を教えてください。

4

8 に答える 8

58

戦略パターンを見てみてください。

  • 応答を処理するためのインターフェイス クラスを作成します (IMyResponse)
    • この IMyResponse を使用して、AdvisoryBoardResponse、EditorialBoardResponse クラスを作成します
  • soapresponse 値をキーとして、戦略を値としてディクショナリを作成します
  • 次に、辞書から取得して IMyResponse クラスのメソッドを使用できます。

ちょっとした例:

// Interface
public interface IResponseHandler {
   public void handleResponse(XmlPullParser xxp);

}

// Concrete class for EditorialOffice response
private class EditorialOfficeHandler implements IResponseHandler {
   public void handleResponse(XmlPullParser xxp) {
       // Do something to handle Editorial Office response
   }
}

// Concrete class for EditorialBoard response
private class EditorialBoardHandler implements IResponseHandler {
   public void handleResponse(XmlPullParser xxp) {
       // Do something to handle Editorial Board response
   }
}

ハンドラーを作成する必要がある場所で:

Map<String, IResponseHandler> strategyHandlers = new HashMap<String,IResponseHandler>();
strategyHandlers.put("EditorialOffice", new EditorialOfficeHandler());
strategyHandlers.put("EditorialBoard", new EditorialBoardHandler());

応答を受け取った場所:

IResponseHandler responseHandler = strategyHandlers.get(soapResponse);
responseHandler.handleResponse(xxp);
于 2012-04-16T14:22:13.953 に答える
34

この特定のケースでは、コードは、追加される文字列を除いて3つのケースすべてで基本的に同一であるため、構築される各文字列のマップエントリがあります。

Map<String,String> map = new HashMap<String,String>();
map.put("EditorialOffice","");
map.put("EditorialBoard","");
map.put("AdvisoryBoard","");
// could make constants for above Strings, or even an enum

次に、コードを次のように変更します

if(eventType == XmlPullParser.START_TAG) {
    soapResponse= xpp.getName().toString();
    String current = map.get(soapResponse);
    if (current != null && xpp.getText()!=null) {
        map.put( soapResponse, current += xpp.getText());
    }
    eventType = xpp.next();
}

「if...then...else」はありません。戦略パターンなどの複数のクラスの複雑さが増すことさえありません。マップはあなたの友達です。戦略は状況によっては素晴らしいですが、これは簡単でなくても解決できます。

于 2012-04-16T14:33:05.357 に答える
10

Java 7 では、文字列を SWITCH できます。あなたがそれを使うことができれば、あなたはそれを使うことができます;-)

于 2012-04-16T14:21:30.107 に答える
6

zzzzzzz(etc.) のコメントに加えて... XmlPullParser を使用していることに注意してください。これにより、あなたが持っているような醜いコードを書くことができます。コードを分割して「より良い」ものにするコールバックを登録することもできますが、可能であれば、SimpleXML ライブラリなどを使用してください。

また、コードをリファクタリングして、読みやすく、冗長性を減らすこともできます。xpp.next()たとえば、各 if ステートメント内で呼び出すのはなぜですか? 一度だけ外部で呼び出してみませんか:

if(eventType == XmlPullParser.START_TAG) {
    soapResponse= xpp.getName().toString();
    if (soapResponse.equals("EditorialOffice") && xpp.getText()!=null){  
        editorialOffice += xpp.getText();
    }   
    else if (soapResponse.equals("EditorialBoard") && xpp.getText()!=null){  
        editorialBoard += xpp.getText();
    }
    else if (soapResponse.equals("AdvisoryBoard") && xpp.getText()!=null){  
        advisoryBoard += xpp.getText();
    }   
}
eventType = xpp.next();
于 2012-04-16T14:20:38.370 に答える
6

if/else コンストラクトの各ブランチに 1 つずつ、3 つの実装を持つ ResponseHandler インターフェイスを作成できます。

次に、さまざまな soapResponses をハンドラーにマップするマップ、またはその soapResponse を処理できる場合はすべてのハンドラーを含むリストを作成します。

また、ボイラープレート コードの一部を、応答ハンドラ クラスの一般的な抽象実装に移動できる必要があります。

多くの場合、これには多くのバリエーションがあります。コードの複製を利用することで、実際に必要な実装は 1 つだけです。

class ResponseHandler{
    String stringToBuild = "" // or what ever you need
    private final String matchString

    ResponseHandler(String aMatchString){
        matchString = aMatchString
    }
    void handle(XppsType xpp){
        if (xpp.getName().toString().equals(matchString){
            eventType = xpp.next();
            if (xpp.getText()!=null){
                 editorialOffice += xpp.getText();
            }
        }
    }
}

あなたのコードは

List<ResponseHandler> handlers = Arrays.asList(
    new ResponseHandler("EditorialOffice"),
    new ResponseHandler("EditorialBoard"),
    new ResponseHandler("AdvisoryBoard"));
if(eventType == XmlPullParser.START_TAG) {
    for(ResponseHandler h : handlers)
        h.handle(xpp);
}
于 2012-04-16T14:26:05.037 に答える
5

Java 7を使用できるかどうか、または実際に使用できるかどうかについては言及していません。そのJavaバージョンでは、switchステートメントで文字列を使用できます。

それ以外は、それぞれの場合のロジックをカプセル化することをお勧めします。たとえば、次のようになります。

Map<String, Department> strategyMap = new HashMap<String, Department>();
strategyMap.put("EditorialOffice", new EditorialOfficeDepartment());
strategyMap.put("EditorialBoard", new EditorialBoardDepartment());
strategyMap.put("AdvisoryBoard", new AdvisoryBoardDepartment());

次に、マップから正しい戦略を選択して使用するだけです。

String soapResponse = xpp.getName();
Department department = strategyMap.get(soapResponse);
department.addText(xpp.getText());

Departmentもちろんインターフェースにあります...

于 2012-04-16T15:26:22.757 に答える
5

広大な質問はこれであり、本当の答えはありません。(石鹸はあまり使いません)

ここにあなたのコードに基づいたいくつかのアイデアがあります:

まず、重複コードをグループ化できます

if (soapResponse.equals("EditorialOffice")
||soapResponse.equals("EditorialBoard")
||soapResponse.equals("AdvisoryBoard")){ 

あなたができるもう一つの良いことは、次のようなスイッチステートメントで遊ぶことです:

switch(soapResponse){
case "EditorialOffice":
case "EditorialBoard":
case "AdvisoryBoard":
eventType = xpp.next();
                if (xpp.getText()!=null){
                advisoryBoard += xpp.getText();
                }
break;

また、テストを小さな関数に分割することを検討する必要があります。

public bool interestingTag(string s){
return (soapResponse.equals("EditorialOffice")
    ||soapResponse.equals("EditorialBoard")
    ||soapResponse.equals("AdvisoryBoard"));
}

    public processData(xpp){
    eventType = xpp.next();
                    if (xpp.getText()!=null){
                    editorialBoard += xpp.getText();
                    }
    ....}

whileループですべての回答を処理できるように、elseが5〜10行の関数になると非常に長くなります

しかし、私が言ったように、同じことを行う良い方法はたくさんあります

于 2012-04-16T14:28:52.740 に答える