2013-10-16 4 views
0

하나의 번역 서버를 디자인하려고합니다. 로컬 시스템에는 하나의 POJO 클래스 (RootClass)가 있습니다. 내 시스템에 원격 객체 (RemoteClass)를 전송하는 원격 시스템도 있습니다. 이 서비스의 책임은 Remote class를 Root class로 변환하는 것입니다. 문제는 다음과 같습니다. 많은 유형이 있습니다. 예 : 200 종류 이상. 나는이 번역을하기 위해 거대한 if-else를 써야한다 :번역 레이어 디자인

나는이 질문을 기술하기 위해 몇 가지 의사 코드를 열거한다.

public class RootClass { 
    public String type; 
    public String attr1; 
    public String attr2; 
    public String attr3; 
    public String attr4; 
} 


public class RemoteClass { 
    public String type; 
    public String attr1; 
    public String attr2; 
    public String attr3; 
} 


public class Translator{ 

    public RootClass translate(RemoteClass remote) { 
     RootClass root = new RootClass(); 

     if ("a".equals(remote.type)) { 
      root.type = "veryGood"; 
      if ("one".equals(remote.attr1)) { 
        root.attr2 = "true"; 
      } 
      if ("two".equals(remote.attr1)) { 
       root.attr3 = "true"; 
      } 
      if ("1".equals(remote.attr1) && "2".equals(remote.attr2)) { 
       root.attr4 ="good"; 
      } 

     } else if ("b".equals(remote.type)) { 
      root.type = "good"; 
      if ("one".equals(remote.attr1)) { 
       root.attr2 = "1"; 
      } else if ("two".equals(remote.attr1)) { 
       root.attr2 ="2"; 
      } 

     } else if ("c".equals(remote.type)) { 
      root.type = "good"; 
      if (remote.attr2.indexOf(":") > 0) { 
       String[] strArray = remote.attr2.split(":"); 
       root.attr2=strArray[0]; 
       root.attr3=strArray[1]; 
      } 

     } 

    } 
} 

2 개체는 완전히 다른 구조로 1 가지를 설명합니다. 루트 클래스는 우리 시스템의 커널이며 스트럿을 할 수 없으며이 루트 클래스는 로컬 시스템에 매우 적합하다고 생각합니다. Remote 클래스는 우리가 변경할 수있는 권한이없는 제 3 자 시스템에서 왔습니다. 그래서이 번역은 매우 어려워졌습니다. 내가 번역을 위해 200 개 이상의 채택을 만들 수 있습니다 제거 할 계획 무엇

: 예 :

public class adopterA implements RootAdoper { 
public RootClass translate(RemoteClass remote) { 
    RootClass root = new RootClass(); 
    root.type="veryGood"; 
    if ("one".equals(remote.attr1)) { 
     root.attr2 = "true"; 
    } 
    if ("two".equals(remote.attr1)) { 
     root.attr3 = "true"; 
    } 
    if ("1".equals(remote.attr1) && "2".equals(remote.attr2)) { 
     root.attr4 ="good"; 
    } 
} 

}

그리고 HasMap에 여전히

Map<String, RootAdoper> map = new HashMap<String, RootAdoper>(); 

그러나 한을 그 모두를 넣어 if/else를 감싸는 200 개의 작은 클래스,이 복잡한 문제를 해결하기위한 좋은 패턴이나 디자인이 있습니까? 미리 감사드립니다.

답변

1

지도의 키는 무엇입니까? 키가 Remote.type 경우 다음 당신은 블록 경우 경우/다른 사람을 제거 않습니다

rootClass = map.get(remote.type).translate(remote); 

을 수행 할 수 있습니다. 알려지지 않은/번역되지 않은 영역을 처리하거나 기본 번역을 수행하지 않거나 수행하지 않는 NullObject을 지정하십시오.

라고 패턴에 책 리팩토링에서 이에 대한 기술 이름이

"명령 조건부 Dispatcher를 바꾸기"당신은 여전히하지만지도를 채울 수 있습니다. 아마도 이것을 수행하는 한 가지 방법은 모든 RootAdoper 인터페이스를 열거 형으로 만들고 모든 구현을 열거 형의 형식으로 만드는 것입니다. 열거 형에 새 메서드를 추가하여 각 값을 변환 할 수있는 Remote.Type을 가져올 수도 있습니다.

enum RootAdoper{ 

    A{ 
     @Overide 
     public RootClass translate(RemoteClass remote){ 
      //... 
     } 

     @Override 
     public String getTypeToTranslate(){ 
      return "A"; 
     } 
    }, 
    ... // other types listed here similarly 
    ; 

    abstract RootClass translate(RemoteClass remote); 

    abstract String getTypeToTranslate(); 
} 

그런 다음이

Map<String, RootAdoper> map = new HashMap<String, RootAdoper>(); 

for(RootAdoper adoper : RootAdoper.values(){ 
     map.put(adoper.getTypeToTranslate(), adoper); 
} 
+0

감사처럼지도를 채울 수 있습니다. enum을 사용할 때 더 좋습니다. 좋은 생각. 하지만이 열거 형은 여전히 ​​크다. 이 모든 것을 구성 할 수있는 방법이 있습니까? 나는 보통 도메인 전문가로부터 모든 정보를 얻었습니다. 그 정보를 수집하여 코드를 작성한 다음 코드 작업을합니다. 이 모든 것을 구성 할 수 있으며, 많은 작업을 줄일 수 있습니다. 나는 의미한다 : A : VeryGood. B : 좋습니다. DB 또는 소스 코드에서 쉽게 구성 할 수 있습니다. 그러나 다른 복잡한 규칙'(remote.attr2.indexOf (":"))'는이 방법을 사용하기가 매우 어렵습니다. 당신은 리팩토링에 능숙합니다. 그래서 이것에 대한 제안을 해주실 수 있습니다. – Bensson

+0

코드를 작성한 클래스 또는 DB 또는 Excel 파일을 읽음으로써 동적으로 생성 된 클래스 모두 좋은 옵션입니다. 나는 번역의 규칙이 얼마나 자주 바뀌는가에 따라 다른 하나를 선호 할 것이다.규칙을 변경하거나 코드를 다시 작성해야하는 경우가 드물게 변경되는 경우 위에 설명한 방법으로 이동하십시오. 코드를 한 번 쓰는 것만으로도 효과가 있습니다. DB 또는 config/excel을 읽는 것은 구성을 구문 분석하는 데 하나 이상의 변환기가 필요하기 때문에 더 복잡합니다. 그러면 많은 클래스로 끝납니다. – dkatzel

+0

답변 해 주셔서 감사합니다. – Bensson