2013-01-10 6 views
5

일부 코드 (Java)를 검토하고 비즈니스 논리 흐름 차트를 기반으로 변경합니다. 현재 코드는 많은 양의 if 문을 사용합니다. 시도하고 싶은 곳에서 멀리 떨어져 있습니다. 나는 다형성에 대해 읽었으며, 내 상황에 그것을 적용하는 방법에 대해 머리를 감싸려고 노력하고있다. 하나의 조건부 레벨에서 작동하도록 만들 수 있지만 여러 조건부 레벨에서 더 확장해야하는 어려움이 있습니다. 이 코드는 이전 단계의 변수가 전달되는 'Logic'메소드를 사용하여 런타임에 실행됩니다.다른 스위치/중첩 피하기 - Java

실례 : 우리는 2 개의 동물원 '동물원 A'와 '동물원 B'와 '집'을 가지고 있습니다. 이들 각각은 '장소'입니다. 각 동물원에는 4 개의 '위치', '북쪽', '남쪽', '동쪽'및 '서쪽'이 있습니다. '집'에는 위치가 하나뿐입니다. 우리는 몇 가지 변수에 기초하여 사람에게 '목적지'를 지정하려고합니다. 이 변수는 다음과 같습니다. '장소'는 우리 장소 (동물원 A, 동물원 B, 집)와 관련이 있습니다. 'Direction'은 Google의 위치 (N, S, E, W)와 관련이 있습니다. 흐름 차트 :

그래서
   |----- | 'HOME' 
       |Place?| ----- > *destination = 'home'* 
       |----- | 
    Zoo A   |        Zoo B 
    |---------------|----------------------------------------| 
|----------|          |----------| 
|Direction?|          |Direction?| 
|----------|          |----------| 
    | North           | North 
    ----------- *destination = 'Zoo A North'   ----------- *destination = 'Zoo B North' 
    | East           | East 
    ----------- *destination = 'Zoo A East'    ----------- *destination = 'Zoo B East' 
    | South           | South 
    ----------- *destination = 'Zoo A South'   ----------- *destination = 'Zoo B South' 
    | West           | West 
    ----------- *destination = 'Zoo A West'    ----------- *destination = 'Zoo B West' 

사람 X는 동물원 (A)의 장소와 남부의 방향이있는 경우가의 대상을 가져야한다 '동물원 남쪽의'

내가 사용 현재 아주 못생긴 코드를 if 문 :

if(Place = 'HOME') 
    destination = 'HOME' 
if(Place = 'Zoo A') 
    if(Direction = North) 
     destination = 'Zoo A North') 
    if(Direct = East) 
     destination = 'Zoo A East') 
    ... 
if(Place = 'Zoo B') 
    if(Direction = North) 
     destination = 'Zoo B North') 
    if(Direct = East) 
     destination = 'Zoo B East') 
    ... 

변수를 ENUM으로 사용하여 중첩 된 스위치로 전환 할 수 있습니다. 그러나 나는 그것으로 떨어지는 나쁜 습관을 가지고 있기 때문에 if - else/switch 의존성을 피하려고 노력하고있다. 팩토리 디자인을 사용하여 장소 클래스를 생성 한 다음 각 위치 및 대상에서 다형성을 사용하여 실험했지만 지나치게 복잡해지기 시작했습니다. if/switch에서 벗어날 가치가 있습니까? 나는 단지 그것을 과도하게 만들려고 노력하고 있는가?

로직 태클 방법에 대한 제안 사항은 다음과 같습니다. 감사합니다

+0

예를 들어 무엇을 하려는지 완전히 명확하지 않습니다. "장소"와 "방향"문자열 또는 다른 종류의 객체입니까? 어느 쪽이든, 간단한 예제는'Zoo' 클래스에서'goNorth()'메소드 등을 만드는 것일 수 있습니다. 나는 이것이 당신의 문제를 해결할 것이라는 것을 완전히 확신하지는 못합니다. 왜냐하면 당신이하려고하는 것에 대해 완전히 명확하지 않기 때문입니다. –

+0

@ Code-Guru - 단순화를 위해 모든 문자열을 사용한다고 가정 해 보겠습니다. 내가하려는 것은 흐름의 상단에서 시작하고 변수 (방향 및 장소)에 따라 최종 '목적지'로 끝납니다. 그러나 가장 관리하기 쉽고 유지하기 쉬운 방법으로 유지하려면 – NathanS

답변

3

것은 이것은 다음과 같이 모델링 할 수 while 루프를 사용하여 시도 할 수 있습니다 :

  1. 이 방법 calculateDestination(Person)와 루트 클래스 Place을 사용합니다. 장소는 그 안에 다른 장소로 구성 될 수 있습니다.
  2. Zoo 및 (자연스럽게 실제 장소이므로) Place 하위 클래스를 만듭니다.
  3. Person 객체 지금 currentPlacecurrentDirection

당신이 당신의 상황을 표현하기 위해 이러한 클래스의 객체를 인스턴스화 줄의 값을 가지고 : 당신이 목적지에 도착 할 때

zooA = new Zoo("ZooA"); 
zooA.addChild(new ZooQuadrant(Direction.SOUTH)); 
... so on for every quadrant ... 
... same for zooB ... 
home = new Place("Home"); 
world = new Place("World"); 
world.addChild(home); 
world.addChild(zooA); 
world.addChild(zooB); 

을, 당신은 부를 것이다 world.calculateDestination(myPerson)

calculateDestination(Person)은 다형성 방법입니다. 상속 계층의 각 수준은 해당 클래스의 특정 의미에 따라 재정의합니다.

  1. PlacePerson 인스턴스 (currentPlace에 대한 Person의 값에 대한 테스트로) 해당 노드에서 현재의 경우 테스트하고하지 않을 경우, 그것은 그 아이의 각각에 calculateDestination를 호출 일반적인 구현을해야합니다 그것을 돌려 보내라.
  2. Zoo의 경우 currentPlace == this인지 확인하고, 그렇다면 각 사분면에 calculateDestination으로 전화하여 긍정 결과를 조합하여 this.name + quadrantResult을 반환해야합니다.
  3. ZooQuadrantcurrentDirection이 해당 방향과 동일한 지 확인하고 이에 따라 값을 반환하면됩니다.

참고 : 이것은 다형성이 어떻게 작용 하는지를 보여주기위한 것일뿐 더 나은 구현이 될 수 있습니다. 또한 여기서 우리는 다형성과 재귀를 모두 사용하고 있습니다. 두 개는 독립적입니다.


편집 : 복잡성이 보증 여부에 관해서는

, 달려! 여기서 우리는 아주 작은 객체 그래프를 가진 간단한 예제로 작업하고 있습니다. 수십 개의 동물원이 생기 자마자 그 동물원에 더 많은 사분면을 추가해야합니다. 예를 들어 각 사분면에 하위 사 분위수가있는 경우 추가 수준의 결정을 내려야하며, 중첩 된 if-else-if 방법 (절차 적) 정말 털이 빠르다. 반면 객체 지향 접근법은 유지되고 이해할 만하다.

모든 것이 그렇듯이 결정이 복잡해 지리라 예상하면 OO 접근 방식을 사용하십시오. 그렇지 않은 경우, 매번 아름다움을 간단하게 유지하십시오. 올바른 문제에 맞는 도구를 사용하십시오.

+0

제안 해 주셔서 감사합니다.이 작업 모델을 구축했습니다. (게시물이 너무 길어서 :(). 나는 그것을보고 있으면 내가하고있는 일을 복잡하게하려고 노력하고 있다고 생각합니다. 잘 작동합니다! .. – NathanS

0

하나의 접근 방식은 getNorthDestination(), getEastDestination() 등의 메소드로 부모 클래스/인터페이스 'Place'를 만들 수 있습니다.

은 그럼 당신은 'ZooA'와 'ZooB'라는 '장소'의 서브 클래스/구현을 만들고, 재정/I 적어도 세 가지 클래스를 참조 이로부터 위치

+0

이 더 많은 일을해야합니다. 방향을 추가하는 것은 동쪽, 위, 아래로 당신은 많은 장소에 방법을 추가해야하는 바람입니다. – BevynQ

+0

그건 내가 피하고 싶은, 새로운 동물원을 추가 할 미래의 변화, 또는 논리를 깨뜨리지 않는 새로운 방향입니다. @gerrytan - 좋은 생각인데 if 블록을 if (Place place = 동물원 A)로 돌려 놓으면 Place = new Zoo A'를 반환 할 것입니다. 그러면 Direction에서 스위치를 호출하면됩니다. case North : place.goNorth();'. 그게 맞습니까? – NathanS

0

에게 해당 반환 할 getXXXDestination() 메소드를 구현 장소, 방향 및 목적지가되고 싶습니다.

장소에는 name 속성과 getName() 메서드가 있으며 이름은 Zoo A, Zoo B, Home으로 설정됩니다.

행동이 다른 경우 집 및 동물원 하위 클래스를 만들 수 있습니다. 홈에는 방향이 없지만 동물원에서는 방향이 없기 때문에이 경우 할 수 있습니다.

Direction은 North, East, West, South를 포함하는 enum (클래스의 특별한 유형) 일 수 있습니다.

대상에는 장소와 방향이라는 두 가지 속성이 있습니다. 또한 메소드 getDestination()이 있습니다.

public String getDestination(){ 
    if (this.direction == null){ 
     result = this.place.getName(); 
    } else { 
     result = this.place.getName() + " " + this.direction.getName(); 
    } 
    return result; 
} 
0

gerrytan의 답변으로 이동하십시오. 모든 정보에 대해, "정말로이 수업이 필요합니까?"라고 자문해야합니다. 여러 번, 대답은 '아니오'입니다. 간단한 문자열/숫자 변수로 충분합니다.자, 여러분은 이러한 변수를 getter/setter 메소드와 결합하기를 원합니다. 이것은 public 변수를 직접 참조하는 것과는 반대로 (예 : C++) java가 강조하는 것과 같습니다. 간단한 메소드를 참조하는 것은 예를 들어 테스트하는 것보다 훨씬 쉽습니다.

0

당신은 당신이 directionForZoo()처럼 호출 할 수 있습니다 ...... 그 안에 동물원 A와 동물원 B와 새로운 방법을하고, 경우에하는 것은

0

엔지니어를 과도하게 사용하지 않으려는 경우 다음 해결 방법을 사용하면 if/else를 제거하는 간단한 해결 방법이 될 수 있습니다. 그러나 그것은 우아한 접근 방식이 아닙니다.

키가 (장소 + 방향)이고 값이 해당 목적지 인지도를 가질 수 있습니다. 이것은 프로그램의 순간에 Place와 Direction 값이 더 정적이라면 많이 변경 될 것입니다.

예 :

: 지역 정보를 저장하고 목적지를 검색하는지도

Map<String, String> destMap = new HashMap<String, String>(); 
destMap.put("HOME","HOME"); 
destMap.put("Zoo A+North","Zoo A North"); 
destMap.put("Zoo A+East","Zoo A East"); 
destMap.put("Zoo B+North","Zoo B North"); 

의 대상에 대응하는 장소 및 방향에있어서

destMap.get(Place + "+" + Direction); 
0

하여 예에 하나 개의 가능한 솔루션은을 생성한다 (아마도 추상적 인) Location 클래스입니다. 여기에는 대상에 대한 데이터 구조가 포함될 수 있습니다. 이 데이터 구조의 한 가지 가능성은 아마도 Map<Direction, Location>입니다. Direction은 그 방향으로가는 대상인 Location 개체에 매핑되는 키로 사용할 수있는 열거 형입니다. Location을 서브 클래스 화하여 Home, Zoo 등의 클래스를 만들거나 Location을 구별하는 name 필드를 제공 할 수 있습니다. 또는이 두 가지를 조합하여 수행 할 수도 있습니다.

귀하의 요구에 부응 할 수도 있고 그렇지 않을 수도있는 반쯤 구운 디자인임을 유의하십시오. 좋은 객체 지향 설계는 해결하려는 문제에 대한 정확한 요구 사항에 대한 경험과 상세한 지식을 필요로합니다. 나는 약간의 이전 그러나 아주 조금의 이해를 나중에 가지고있다.

0

몇 가지 제안 답변을 변형 해 보았습니다.

중첩 스위치 케이스 블록을 사용하여 종료되었습니다. 가장 이상적이 아니고 피하고 싶었지만 내 목적에 따라 유지 보수가 용이하지 않았습니다 (변경되거나 확장되지 않음).

@Ezequiel Muns 메서드를 올바르게 작동하도록 설정 했으므로 문제가 발생하지는 않습니다.

모든 도움에 감사드립니다.

관련 문제