2009-05-20 4 views
3

계층 적 개체 구조에서 데이터를 상속하는 알려진 패턴이 있습니까? 나는 그것의 'Parent'로부터 'Type'을 상속 받아야하는 계층 적 'Item'구조를 가지고 있습니다 (디폴트와 같은 데이터를 가짐). 하위 항목 유형은 자체 항목에 의해 수정 될 수 있으며 상위 항목 유형이 변경되면 해당 유형이 변경되지 않은 모든 하위 항목은 새로운 유형의 상위 항목을 가져야합니다.C#의 데이터 상속

참고 내가 가짜 수 없습니다 그것은

public string Type 
{ 
    get 
    { 
     if (type == null) 
      return Parent != null ? Parent.Type : null; 

     return type; 
    } 
} 

'와 같은 나는 데이터베이스에 값을 입력해야하고, 구조가 재귀를 사용하고 성능에 대해 걱정하지 너무 깊은 원인. 내가 지금 생각할 수

있는 유일한 방법은 더 좋은 방법이 있나요

public string Type 
{ 
    set 
    { 
     type = value; 
     UpdateUnchangedChildren(value); 
    } 
} 

public int AddChild(Item item) 
{ 
    item.Type = Type; 
    return Items.Add(item); 
} 

입니까? 감사합니다. .

답변

3

일반적으로 다양한 계층 설정/구성의 유지 관리와 관련된 일반적인 문제입니다. 그래서, 그것에 대한 해결책은 "패턴"으로 간주 될 수 있습니다.

  • 정규화 된 구조

는 "Normazlied는"재귀로 구현 된 하나입니다

  • 비정규 구조 :

    어쨌든, 내부 구조의 관점에서 당신은이 주요 옵션이 있습니다. 특정 데이터는 항상 한 곳에서 저장되며, 다른 모든 장소는 데이터를 참조합니다 (예 : 부모에게). 구조는 쉽게 업데이트되지만 문제가 될 수 있습니다.

    "비정규화된"은 모든 노드가 해당 레벨에 대한 전체 설정 집합을 저장한다는 것을 의미하며 노드를 업데이트 할 때마다 계층 구조를 내려 모든 자식 노드를 중재하는 데 시간이 걸립니다. 그러나 독서 작업은 즉각적입니다.

    "비정규 화 된"버전이 더 널리 사용되는 것 같습니다. 설정이 일반적인 시나리오는 드물게 업데이트하는 반면, 자주 읽는 동안 더 나은 읽기 성능이 필요하기 때문입니다. 예를 들어, Windows ACL security model은 "비정규 화 된"접근법을 사용하여 보안 검사를 빠르게합니다. 그들 resolve conflicts between the "inherited" and explicit permissions (ACEs) by checking them in a specific order을 어떻게 읽을 수 있습니다. 특정 시스템에 대한 과잉 공격 일 수 있습니다. 특정 값이 오버라이드되었거나 그 반대로 "기본값"으로 재설정되는 플래그를 가질 수 있습니다 ...

    자세한 내용은 시스템 요구 사항에 따라 필드의 일부가 "정규화"되고 일부는 그렇지 않을 "하이브리드"아키텍처를 가질 수도 있습니다. 그러나 당신은 옳은 길에있는 것처럼 보입니다.

  • 1

    나는 당신이 무엇을하려고하는지 잘 모르겠지만 ... 당신은 자식 객체에 부모 객체의 유형을 전달하기 위해 제네릭을 사용할 수 있습니다 ... 그러나 세터가 없다면 실제로 이해할 수 있습니다 ... Parent 객체의 유형은 인스턴스화 될 때 설정됩니다. 따라서 설정을 변경해야하는 이유는 무엇입니까? 당신은 어떤 유형의 Parent 개체가있을 때

    public class Child<T> 
    { 
        public string Type 
        { 
         get { return typeof(T).ToString(); } 
        } 
    } 
    

    는 그럼, 당신은 당신의 아이 재산권에 그것을 전달할 수 있습니다이 같은 뭔가를

    가정 ...

    public class ParentA 
    { 
        public Child<ParentA> ChildObj { get; set; } 
    } 
    
    public class ParentB 
    { 
        public Child<ParentB> ChildObj { get; set; } 
    } 
    
    public class ParentC 
    { 
        public Child<ParentC> ChildObj { get; set; } 
    } 
    

    ChildObj.Type 속성 중 하나를 호출하면 ParentA, ParentB & 부모 C가 각각 반환됩니다.

    Buit 나는 당신이 무엇을하려고하는지 완전히 설명하지 않은 재미있는 느낌을 가지고 있습니다. 당신은 부모 클래스 & 어린이/항목 클래스

    +0

    좋아, 나는 그것을 더 설명하려고 노력할 것이다. – reticent

    0

    을 보여주는 좀 더 코드 예제를 게시 할 수 "... 구조 성능에 대해 걱정 재귀를 사용하지 너무 깊이입니다."

    실제로 측정 했습니까? 얼마나 많은 아이템을 다루고 있는지, 구조가 얼마나 깊고 아이템이 자신의 "타입"값을 갖고 있지 않은지는 얼마나 흔한가요? 애플리케이션의 성능 목표는 무엇이며 재귀 솔루션은 이러한 목표와 어떻게 비교됩니까?

    사람들이 재귀가 느리다고 생각하는 것이 일반적이므로 시도하지 않고 고려하지 않아도됩니다. 성능상의 이유로 가장 간단한 설계를 먼저 측정하지 않고 거부하는 것은 결코 좋은 생각이 아닙니다. 그렇지 않으면 더 단순한 것이 잘 작동했을 때 더 복잡한 해결책을 고안해냅니다.

    물론 두 번째 해결 방법은 재귀를 사용하고 계층 구조를 위로 이동하는 것뿐입니다. 아이 삽입물이 다른 시간에 발생하고 가능한 성능 저하를 흡수 할 수 있다면 아마도 더 수용 가능할 것입니다.

    +0

    재귀에 대한 좋은 지적이지만 예, 테스트를 마쳤습니다. 게으른 로딩과 재귀가 좋은 쌍을 이루지 못한다고 생각합니다. 값을 변경하는 것보다 값을로드하는 것이 더 빈번하다고 말한 것입니다. – reticent

    1

    명백한 최적화는 유형을 읽을 때 부모로부터 얻은 값을 캐시하는 것입니다. 즉, 각 경로를 한 번만 탐색합니다 (단 순한 해결책은 O (h) 대신 O (h^2)까지 의미하는 경로를 포함하는 각 경로에 대해 반복적으로 각 하위 경로를 통과한다는 것을 의미합니다) . 만약 당신이 글쓰기보다 더 많은 읽기를한다면 그것은 훌륭하게 작동 할 것입니다.

    이것을 고려 :

    class Node 
    { 
        string _cachedParentType = null; 
        string _type; 
        string Type 
        { 
         get { return _type ?? _cachedParentType ?? (_cachedParentType = Parent.Type); } 
         set 
         { 
          _type = value; 
          foreach (var child in Children) { child._cachedParentType = null; } 
         } 
        } 
    } 
    

    이 충분히 읽고 몇 쓰기가 읽기 (1) 최상의 경우 나, 최악는 "캐시 미스가"당신이 O (시간을) 비용 O됩니다와 의미 h는 나무의 높이이다. 업데이트는 O (k)이며, k는 분기 레벨입니다 (하나의 레이어 만 업데이트하므로!). 나는 이것이 UpdateUnchangedChildren 솔루션 (일반적으로 리프 노드에 반복적으로 업데이트 노드가 있다고 가정 함)보다 낫다고 생각한다.

    +0

    leafs까지 노드를 반복적으로 갱신 할 필요가 없습니까? 이렇게하면 손자 노드가 부모 유형 (조부모 유형 임)에 캐시되고 조부모 유형이 변경되면 손자 노드가 잘못된 값을 반환합니다. – reticent