2012-03-26 2 views
2

사전 웹 사이트의 웹 페이지를 구문 분석하는 단어 정의 가져 오기 프로그램을 작성했습니다. 모든 웹 페이지가 정확히 동일한 HTML 구조를 가지고있는 것은 아니므로 대부분의 경우를 지원하는 여러 가지 구문 분석 방법을 구현해야했습니다.반복적 인 대체 메커니즘을 구현하는 디자인 패턴

아래는 내가 지금까지 해본 적이있다. 이것은 꽤 못생긴 코드이다. 나는 N을 구현할 수 있도록 반복적 인 대체 메커니즘 어떤 종류의 코딩의 가장 깨끗한 방법이 될 것 어떻게 생각하십니까

는 방법을 분석하는 순서 (구문 분석 오류가 다음 구문 분석을 트리거합니다 (더 적절한 용어가있을 수 있습니다) IOException과 같은 예외는 프로세스를 중단해야합니다.)

public String[] getDefinition(String word) { 
    String[] returnValue = { "", "" }; 
    returnValue[0] = word; 
    Document doc = null; 
    try { 
     String finalUrl = String.format(_baseUrl, word); 
     Connection con = Jsoup.connect(finalUrl).userAgent("Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17"); 
     doc = con.get(); 
     // *** Case 1 (parsing method that works for 80% of the words) *** 
     String basicFormOfWord = doc.select("DIV.luna-Ent H2.me").first().text().replace("·", ""); 
     String firstPartOfSpeech = doc.select("DIV.luna-Ent SPAN.pg").first().text(); 
     String firstDef = doc.select("DIV.luna-Ent DIV.luna-Ent").first().text(); 

     returnValue[1] = "<b>" + firstPartOfSpeech + "</b><br/>" + firstDef; 
     returnValue[0] = basicFormOfWord; 
    } catch (NullPointerException e) { 
     try { 
      // *** Case 2 (Alternate parsing method - for poorer results) *** 
      String basicFormOfWord = doc.select("DIV.results_content p").first().text().replace("·", ""); 
      String firstDef = doc.select("DIV.results_content").first().text().replace(basicFormOfWord, ""); 

      returnValue[1] = firstDef; 
      returnValue[0] = basicFormOfWord; 
     } catch (Exception e2) { 
      e2.printStackTrace(); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return returnValue; 
} 
+1

당신의 체인을 고려할 수 세바스티앙의 주석으로 코드를 수정 책임 [패턴] (http://www.javacamp.org/designPattern/chains.html) – Renard

답변

1

이미 언급했듯이 연쇄 성은 좋은 후보입니다. John의 답변 UrlParser가 다음 파서에 대한 요청을 처리할지 여부를 적극적으로 결정하지 않기 때문에 OTOH는 적절한 의미로 책임을지지 않습니다. 는 여기에 내 사소한 샷입니다 :

public class ParserChain { 
    private ArrayList<UrlParser> chain = new ArrayList<UrlParser>(); 
    private int index = 0; 
    public void add(UrlParser parser) { 
     chain.add(parser); 
    } 
    public String[] parse(Document doc) throws IOException { 
     if (index = chain.size()){ 
      return null; 
     } 
     return chain.get(index++).parse(doc); 
    } 
} 

public interface UrlParser { 
    public String[] parse(Document doc, ParserChain chain) throws IOException; 
} 

public abstract class AbstractUrlParser implements UrlParser { 
    @Override 
    public String[] parse(Document doc, ParserChain chain) throws IOException { 
     try { 
      return this.doParse(doc); 
     } catch (ParseException pe) { 
      return chain.parse(doc); 
     } 
    } 
    protected abstract String[] doParse(Document doc) throws ParseException, IOException; 
} 

주목할만한 일 :

  • 이 코드는 일부 파서이 멈출 때까지,이 들어가는 모든 파서 UrlParser 번호 구문 분석에 대한 스택 ParserChain 번호 구문 분석에 대한 프레임을 유지 책임의 사슬. 거대한 체인이있는 경우 스택 오버플로 (적절한 방법)로 실행할 수 있습니다.
  • AbstractUrlParser를 확장하지 않는 UrlParser는 인수 String을 수정하고 체인의 다음 노드를 위임하거나 다음 체인을 위임 한 다음 결과.
  • ParserChain 안전 - 스레드되지 않은 (하지만이 책임 패턴의 사슬에 내재 뭔가 말하고 싶지만)

편집 :

+0

고마워, 나는 네 제안에 충실 할 것 같아. 마지막 return 문은'return chain.parse (doc);이라고 생각합니다. –

2

Chain-of-Responsibility과 같은 패턴으로 들립니다. 나는 다음과 같은 것이다 :

public interface UrlParser(){ 
    public Optional<String[]> getDefinition(String word) throws IOException; 
} 

public class Chain{ 
    private List<UrlParser> list; 

    @Nullable 
    public String[] getDefinition(String word) throws IOException{ 
     for (UrlParser parser : list){ 
      Optional<String[]> result = parser.getDefinition(word); 
      if (result.isPresent()){ 
       return result.get(); 
      } 
     } 
     return null; 
    } 
} 

내가 구아바의 Optional 여기를 사용하고을하지만 당신은뿐만 아니라 인터페이스에서 @Nullable를 반환 할 수 있습니다. 그런 다음 필요한 각 URL 파서에 대한 클래스를 정의하고 여기에 삽입하십시오. Chain

관련 문제