2013-10-18 1 views
1

이론상 이론 상으로는 복합 및 반복기 디자인 패턴에 가장 적합 할 수 있지만 이러한 패턴을 가진 문제는 기본 데이터 구조에 액세스 할 수 없다는 것입니다. 협상 단속 자라.Composite/Iterator 디자인 패턴에서 실제 값을 확인하지 못했습니다.

확실히 나는 나라의 한 도시에있는 쇼핑몰을 가질 수 있으며 이것은 부분적인 관계를 만든다. 그리고 내가 그것의 합성 패턴을 만들면 나는 모든 시간 (모든 부분에 대해)에 대해 공통적 인 방법을 실행할 수있다. 상점/쇼핑몰이 열리고 닫히지 만 실제로는 그 이상이 필요합니다.

예를 들어 이미 저장된 파일에서 이러한 복합 구조를 트리 컨트롤로로드하는 간단한 작업을 예로 들어 보겠습니다. 이제 우리는 어떤 컴포넌트가 무엇인지조차 알지 못하기 때문에 트리에서 컴포넌트가 부모, 형제 또는 자식이어야하는지 여부조차 확인할 수 없습니다. 우리는 근본적으로 어떤 유형의 복합 패턴이 처음부터 반대인지를 확인하기 위해 일종의 유형 검사를해야합니다. 이것은 외부 반복자에서 특히 그렇습니다.

처음에는 조합 된 두 패턴이 더 큰 잠재력을 가진 것처럼 보였지만 이제는 거의 사용하지 않는 것처럼 보입니다.

나는이 두 패턴에 대한 참된 정당성을 찾으려고합니다. Print()cost()와 같은 간단한 텍스트 북 예제 이외의 다른 곳에서는 사용할 수 있습니다. 파일에서로드 될 때 합성의 계층 구조를 반영하기 위해 트리 컨트롤을 채우기 위해 합성을 다시 유형 변환해야합니까?

답변

4

iterator이 필요하지 않은 경우 visitor이 필요합니다.

반복자는 일정한 개체를 나타냅니다. 귀하의 개체는 확실히 이 아니며 유니폼입니다. 또한, composite은 객체가 균일 한 방법으로 사용될 때 더 잘 작동하는 경향이 있습니다. 하나의 고전적인 예는 계산식입니다. 다른 하나는 화면에 렌더링하는 기하학적 인 도형입니다. 상점과 카운티가 공통점이 너무 많지 않기 때문에 고전적인 복합 패턴에 대한 귀하의 사례는 적합하지 않습니다.

다행히도 방문자는 도시, 카운티, 쇼핑몰 및 상점에서해야 할 일을 알고있는 방문자 클래스를 정의합니다. 이러한 각 클래스를 "방문 가능"하게 만들고 복합 클래스로 배열하십시오. 이제 컴포지트에서 클래스의 통합 속성은 각 클래스를 방문 할 수 있다는 것입니다. 리프 클래스는 방문자를 콜백하고 인수로 전달합니다. 지점 클래스는 먼저 자신을 전달한 다음 방문자를 모든 구성 요소로 전달합니다. 이렇게하면 멋지고 깨끗한 방식으로 전체 계층 구조를 탐색 할 수 있습니다.

class County; 
class City; 
class Mall; 
class Shop; 

struct ShoppingVisitor { 
    virtual void visitCounty(const County& county); 
    virtual void visitCity(const City& city); 
    virtual void visitMall(const Mall& mall); 
    virtual void visitShop(const Shop& shop); 
}; 
struct ShoppingVisitable { 
    virtual void accept(ShoppingVisitor& visitor) const; 
}; 
class County : public ShoppingVisitable { 
    vector<ShoppingVisitable*> children; 
public: 
    virtual void accept(ShoppingVisitor& visitor) const { 
     visitor.visitCounty(*this); 
     for (int i = 0; i != children.size() ; i++) { 
      children[i]->accept(visitor); 
     } 
    } 
}; 
class City : public ShoppingVisitable { 
    vector<ShoppingVisitable*> children; 
public: 
    virtual void accept(ShoppingVisitor& visitor) const { 
     visitor.visitCity(*this); 
     for (int i = 0; i != children.size() ; i++) { 
      children[i]->accept(visitor); 
     } 
    } 
}; 
struct Mall : public ShoppingVisitable { 
    virtual void accept(ShoppingVisitor& visitor) const { 
     visitor.visitMall(*this); 
    } 
}; 
struct Shop : public ShoppingVisitable { 
    virtual void accept(ShoppingVisitor& visitor) const { 
     visitor.visitShop(*this); 
    } 
}; 
+0

고맙습니다. 복합성은 방문자의 것입니다. 나는 그것을 모두 이해하기 위해 방문자를 새로 고쳐야하고, 더 생각해야합니다. – zar

+0

내 방문객이 상점/쇼핑몰 등에서 개인 건축물에 액세스해야하는 경우에도 여전히 액세스 할 수 없습니다. 또한이 전체 데이터 (계층 구조)를 구조와 같은 (논리적으로) 트리에서 더 나은 파일에 저장해야합니다. 그 파일에서이 모든 데이터를로드 할 수 있어야합니다. 방문자가 그 문제를 해결하는지 확실하지 않습니다. – zar

+0

@zadane 방문자 (또는 다른 모든 클래스)는 다른 클래스의 개인 구조에 액세스 할 수 없어야합니다. 그러한 개인 구조에 대한 액세스 권한을 부여해야하는 경우 해당 방문객을 다른 클래스의 '친구'로 선언하십시오. 계층 구조를 탐색하고 결과를 파일에 기록하는 방문자를 정의하여 계층 구조를 작성하는 데 쉽게 사용할 수 있습니다. 그러나 방문자가 클래스가 메모리에 있어야하기 때문에 데이터를 다시 읽으려면 코드가 필요합니다. – dasblinkenlight

0

복합체의 외부 호환 STL 반복자의 예에서이 composite-iterator GitHub의 저장소를 참조. 순방향 반복자입니다. * iter는 기본 클래스 인 Node를 반환합니다. 복합 요소는 패턴 해치의 파일 시스템 예제입니다. p. 설명 및 클래스 다이어그램은 slides 중 25 개입니다. 디렉토리는 복합 요소입니다. 리프 노드는 File 인스턴스이고 두 노드의 기본 구성 요소 클래스는 Node입니다. 예

Directory::iterator iter_current = top.begin(); 
Directory::iterator iter_end = top.end(); 

for (;iter_current != iter_end; ++iter_current) { 

     Node &node = *iter_current; 

     cout << "[address: " << hex << &node << "] " << node.getName(); 

     if (dynamic_cast<Directory*>(&node)) { 

      cout << " is a Directory "; 
     } else { 
      cout << " is a File "; 
     } 
     cout << endl; 
} 
관련 문제