2011-04-19 10 views
2

instanceof 또는 이와 동등한 코드 (http://www.javapractices.com/topic/TopicAction.do?Id=31, when should we use instanceof and when not)를 사용하는 것이 좋지 않다고 생각합니다. 주로 재사용하기가 어렵 기 때문에 동의 할 수 있습니다.instanceof 대신 사용할 수 있습니까?

그러나 일부 경우에는 instanceof에 대한 대안으로 생각하기가 어려웠습니다. 예를 들어, 실시간 전략 게임을 만들고 싶다고합시다. 이 게임은 장애물, 건물 및 탱크로 구성되며 모두 격자에 배치되며 각 권한은 격자에서 정확히 하나의 단위를 차지합니다. 그래서 나는 Obstacle, Building 및 Tank 클래스의 수퍼 클래스 인 Entity 클래스를 생성합니다. 그리드는 엔티티의 인스턴스로 구성됩니다. 업데이트가 진행되는 동안 각 탱크가 범위 내의 적 탱크를 조준하고 쏴야합니다. 따라서 쉬운 방법은 각 탱크가 탱크 범위 내의 모든 엔티티를 그리드에 요청한 다음 모든 엔티티를 반복하고 탱크 Tank의 인스턴스인지 확인하는 것입니다.

instanceof를 사용하는 것의 대안으로, 디자인 패턴 Visitor을 사용했습니다. 방문객은 엔터티 (entity->acceptVisitor(visitor))에 의해 받아 들여지고, 그러면 visitor->visitObstacle(this), visitor->visitBuildig(this) 또는 visitor->visitTank(this) 중 하나가 호출됩니다. 그러나 이것은 많은 방문객을 만들어야했습니다. 실제로 엔티티를 만들고자하는 모든 작업마다 새로운 것이 하나 있습니다. 또 다른 문제는 많은 경우 방문자가 어떤 클래스를 구성하든 엔티티에서 동일한 메소드를 호출한다는 것입니다.

파이썬 코드 : 나는 물론,이 경우 기업은 또 다른 엔티티 경우를 물어 보자 수

class StationaryEntityGatherVisitor: 
    def __init__(self): 
     self.stationaryEntities = [] 

    def visitObstacle(self, obstacle): 
     self._addIfStationary(obstacle) 

    def visitBuildig(self, building): 
     self._addIfStationary(building) 

    def visitTank(self, tank): 
     self._addIfStationary(tank) 

    def _addIfStationary(self, entity): 
     if entity.isStationary(): 
      self.stationaryEntities.append(entity) 

    def getStationaryEntities(): 
     return self.stationaryEntities 

기업이 다른 기업이 정지 여부가 있는지 확인하고자 할 때, 예를 들면 일어날 수 그것은 방문자가 그렇게하는 대신에 직접 움직이지 않습니다. 그러나이 경우 엔티티의 속성을 확인하는 데있어 일관성이 없습니다. 엔티티 유형을 확인해야하는지에 따라 엔티티에게 (직접 또는 방문자를 통해) 일부 속성을 묻는 메소드가 달라 지도록하려면 내 의견으로는 꽤 이상한 디자인처럼 보일 것입니다.

그래서 위에서 설명한 문제에서 instanceof를 사용하는 대신 다른 방법이 있습니까?

감사합니다. Martin

답변

1

초 동안 당신의 방문자 솔루션을 잊고, 그리고 당신의 요구 사항에 집중 :

그리드는 엔티티의 인스턴스로 구성되어 있습니다.업데이트가 진행되는 동안 각 탱크가 범위 내의 적 탱크를 조준하고 쏴야합니다. 따라서 쉬운 방법은 각 탱크가 탱크 범위 내의 모든 엔티티를 그리드에 요청한 다음 모든 엔티티를 반복하고 탱크 Tank의 인스턴스인지 확인하는 것입니다.

목록을 직접 필터링하지 않는 이유는 무엇입니까?

targetablesInRange = filter(isTargetable, grid.itemsInRangeOf(self)) 

그냥 탱크 대신 대상이되는 엔티티의 속성에 대해 질문해야합니다. 이것은 기본 클래스에서 false를 반환 할 수 있으며 나중에 시작해야하는 Tank 및 다른 클래스에 의해 무시 될 수 있습니다.

0

글쎄, 모든 탱크에 걸쳐 iterating 여부를 그들이 범위에있는 모든 엔티티 대신 범위에 있는지 탱크를 볼 수 iterating 고려 해 봤나? iteration과 instanceof 호출에서 많은 시간을 절약 할 수있는 것처럼 보입니다 ...

0

일반적으로 다형성은 불필요한 instanceof 연산자를 피하는 방법입니다.

0

Visitor를 사용하여이 동작을 처리해야하는지 여부를 알 수 없습니다. 귀하의 사례는 일반적인 다형성을 사용하여 매우 쉽게 달성 될 수 있습니다. 나는 초기에 팩토리 메소드와 타입 변수를 제안하려고했지만 솔루션은 더 간단해질 수있다.

일반적인 추상 수퍼 클래스가 있습니다. (실재). 그래서이 클래스에서 hitByMissile() (또는 무엇이든)이라는 메서드를 정의 할 수 있습니다. 탱크 클래스에서는 hitByMissile을 수행하고, 장애물과 달리 수행 할 수 있습니다. 코드가 각 엔터티의 동작 방식을 결정해서는 안됩니다. 동작은 객체 자체에 의해 정의되어야합니다. 따라서 엔터티를 반복하고 메서드를 호출 할 수 있습니다.

+0

저는이 문제점을 이해하지 못했을 수 있다는 면책 조항과 함께 모든 답변을 시작하는 습관이 있습니다. :) 이것은 일반적인 snobbishness를 피하기위한 것이지만, 해결책이 당신을 위해 잘 작동하지 않는다면 저에게 의견을 말하십시오. –

관련 문제