2014-02-25 2 views
2

일부 모델 클래스와 컨트롤러 (관리자) 클래스가 있습니다. 이상적으로 컨트롤러는 다운 캐스트를하지 않고도 구체적인 모델 유형을 처리해야합니다 (이 경우는 "올바른"것으로 보입니다). Visitor Pattern과 Abstract Factory 패턴을 생각해 봤습니다. 여기 내 모델 계층 구조의 예는 다음과 같습니다모델 객체의 추상 팩토리 내부?

class Animal {}; 
class Dog : public Animal {}; 
class Cat : public Animal {}; 

내 파서가 우리의 데이터 파일 (XML)을 처리 할 때, 특정 요소 유형이 파생 된 다른 (그러나 관련) 유형에 매핑됩니다. 예를 들어, 우리의 XML은 다른 동물을 정의하고 적절한 구체 유형을 각 동물에 매핑합니다 (데이터가 다양하기 때문에 유니온으로 작동하는 모 놀리 식 "동물"클래스는 피하고 싶기 때문에). 직렬화 클래스의 팩토리 메소드를 통해. 그러나 이들은 컨트롤러에 Animal 개체의 목록으로 저장되어 있으므로 어느 고양이인지, 어떤 개인지 알 수 없습니다.

컨트롤러가 개와 고양이를 다르게 처리해야하는 경우 몇 가지 방법을 사용할 수 있다고 생각합니다.

  1. 컨트롤러 유형 (dynamic_cast는)의 아래쪽 캐스팅을 수행 또는 개체 고양이인지 확인하고 고양이를 처리하는 가상 형 부재를 검사한다. 개들과 동일합니다. 나는이 해결책을 정말로 좋아하지 않는다.
  2. 추상 팩토리 패턴을 활용하여 각 모델에서 각 동물 유형에 해당하는 Controller 객체를 만드는 방법을 알 수 있습니다. 예를 들어 Model::Cat에는 CreateControllerObject() (다형성)이라는 멤버가 있고 CatController 클래스를 반환합니다. 이 솔루션에 대해 잘못된 부분은 Model::Cat 클래스에 약간의 비즈니스 로직이 있다는 것입니다 (예 : 고양이를 만들 수 있음을 알기 전에 수행 할 특정 검사). 일반적으로 모델 객체는 "벙어리 데이터"라고되어 있으므로 "스마트"모델을 가지고 있는지 여부는 확실하지 않습니다.
  3. 방문자 클래스를 Model 클래스에서 직접 사용하십시오. 그러나 이는 모델에 많은 컨트롤러 로직을 포함하므로 # 2를 제안한 것입니다. 적어도 # 2 경우에는 해당 동물 동물 컨트롤러 클래스를 대신 방문 할 수 있습니다.

구현 방법을 잘 모르므로 SO 커뮤니티에서 디자인 아이디어를 얻고 싶습니다. # 2가 가장 정확하고 대충 올바른 방향으로 향하고 있지만 필자가 생각한 솔루션은 없습니다.

+1

을 사용할 수 있습니다, 컨트롤러 로직은없는 모델에서 콘크리트 방문자에 갈 것입니다. – Jarod42

+0

@ Jarod42 내 생각은 정확하게. # 3은 내 목록에 언급되어 있지만 핵심은 컨트롤러 논리를 저장하고 방문자를 구현하기 위해 모델 계층 구조에 해당 컨트롤러 계층 구조가 필요하다는 것입니다. –

답변

1

당신은 방문자 패턴으로 이중 파견을
http://en.wikipedia.org/wiki/Double_dispatch

class Controller 
{ 
public: 
    void update_animal(Dog &dog) { ... } 
    void update_animal(Cat &cat) { ... } 
}; 

class Dog : public Animal 
{ 
public: 
    virtual void update(Controller &controller) 
    { 
     controller.update_animal(*this); 
    } 
} 
// same for Cat 
+0

'Controller'가'IAnimalVisitor'에서 파생 된 경우 * double * dispatch가됩니다. 실제로, * 간단한 * 파견입니다. – Jarod42

+0

@ Jarod42 wikipedia 기사를 보면 이중 디스패치처럼 두 개의 vtable 조회가 필요합니다. 여기의 해결책은 오직 하나의 룩업 (lookup) 만 포함하지만 두 개의 함수 호출 만 포함하므로, 그 표준에 의해 두 배로되지는 않습니다 (하지만 임의의 규칙처럼 보입니다). –

+0

또한 분명히하기 위해'update()'가 Model 클래스 안에 들어갈 것을 제안합니까? 내 모델에서이 작업을 수행하는 것이 좋습니까? 아니면 해당 컨트롤러 객체 (즉,'DogController :: update()')를 생성하여 또 다른 추상화를 생성해야합니까? –

관련 문제