많은 다른 부모 / 자식 클래스가있는 개체 모델을 개발 중입니다. 각 자식 개체에는 부모 개체에 대한 참조가 있습니다. 부모 참조를 초기화하는 몇 가지 방법을 생각할 수는 있지만 각 방법마다 상당한 단점이 있습니다. 아래에 설명 된 접근 방식이 가장 좋거나 더 나은 것을 고려하십시오.
아래 코드가 컴파일되는지 확인하지 않으므로 구문이 정확하지 않은 경우 내 의도를 확인하십시오.
내 자식 클래스 생성자 중 일부는 항상 표시하지는 않지만 부모 이외의 매개 변수를 사용합니다.
발신자는 부모를 설정하고 같은 부모에 추가해야합니다.
class Child { public Child(Parent parent) {Parent=parent;} public Parent Parent {get; private set;} } class Parent { // singleton child public Child Child {get; set;} //children private List<Child> _children = new List<Child>(); public List<Child> Children { get {return _children;} } }
단점 : 상위 설정은 소비자를위한 2 단계 프로세스입니다.
var child = new Child(parent); parent.Children.Add(child);
단점 : 오류가 발생하기 쉽습니다. 호출자는 자식을 초기화하는 데 사용 된 것과 다른 부모에 자식을 추가 할 수 있습니다.
var child = new Child(parent1); parent2.Children.Add(child);
부모는 호출자가 초기화 된 부모에 자식을 추가하는지 확인합니다.
class Child { public Child(Parent parent) {Parent = parent;} public Parent Parent {get; private set;} } class Parent { // singleton child private Child _child; public Child Child { get {return _child;} set { if (value.Parent != this) throw new Exception(); _child=value; } } //children private List<Child> _children = new List<Child>(); public ReadOnlyCollection<Child> Children { get {return _children;} } public void AddChild(Child child) { if (child.Parent != this) throw new Exception(); _children.Add(child); } }
단점 : 발신자에게는 여전히 부모를 설정하는 2 단계 프로세스가 있습니다.
단점 : 런타임 검사 – 성능을 줄이고 모든 추가 / 세터에 코드를 추가합니다.
부모는 자식을 부모에 추가 / 할당 할 때 자식의 부모 참조 (자체로)를 설정합니다. 부모 세터는 내부에 있습니다.
class Child { public Parent Parent {get; internal set;} } class Parent { // singleton child private Child _child; public Child Child { get {return _child;} set { value.Parent = this; _child = value; } } //children private List<Child> _children = new List<Child>(); public ReadOnlyCollection<Child> Children { get {return _children;} } public void AddChild(Child child) { child.Parent = this; _children.Add(child); } }
단점 : 자식은 부모 참조없이 생성됩니다. 때로는 초기화 / 확인에 부모가 필요합니다. 이는 자식의 부모 세터에서 초기화 / 검증을 수행해야 함을 의미합니다. 코드가 복잡해질 수 있습니다. 항상 부모 참조가 있으면 자식을 구현하는 것이 훨씬 쉽습니다.
부모는 팩토리 추가 메소드를 노출하므로 자식은 항상 부모 참조를 갖습니다. 아동 ctor는 내부입니다. 부모 세터는 비공개입니다.
class Child { internal Child(Parent parent, init-params) {Parent = parent;} public Parent Parent {get; private set;} } class Parent { // singleton child public Child Child {get; private set;} public void CreateChild(init-params) { var child = new Child(this, init-params); Child = value; } //children private List<Child> _children = new List<Child>(); public ReadOnlyCollection<Child> Children { get {return _children;} } public Child AddChild(init-params) { var child = new Child(this, init-params); _children.Add(child); return child; } }
단점 : 과 같은 초기화 구문을 사용할 수 없습니다
new Child(){prop = value}
. 대신해야합니다 :var c = parent.AddChild(); c.prop = value;
단점 : 추가 팩토리 메소드에서 하위 생성자의 매개 변수를 복제해야합니다.
단점 : 싱글 톤 자식에는 속성 설정자를 사용할 수 없습니다. 값을 설정하지만 속성 getter를 통해 읽기 액세스를 제공하는 방법이 필요하다는 것은 절망적 인 것 같습니다. 일방적입니다.
자식은 생성자에서 참조 된 부모에 자신을 추가합니다. 아동 ctor는 공개입니다. 부모의 공개 추가 액세스 권한이 없습니다.
//singleton class Child{ public Child(ParentWithChild parent) { Parent = parent; Parent.Child = this; } public ParentWithChild Parent {get; private set;} } class ParentWithChild { public Child Child {get; internal set;} } //children class Child { public Child(ParentWithChildren parent) { Parent = parent; Parent._children.Add(this); } public ParentWithChildren Parent {get; private set;} } class ParentWithChildren { internal List<Child> _children = new List<Child>(); public ReadOnlyCollection<Child> Children { get {return _children;} } }
단점 : 호출 구문이 좋지 않습니다. 일반적으로
add
다음과 같은 객체를 만드는 대신 부모 에서 메소드를 호출합니다 .var parent = new ParentWithChildren(); new Child(parent); //adds child to parent new Child(parent); new Child(parent);
그리고 다음과 같이 객체를 만드는 것이 아니라 속성을 설정합니다.
var parent = new ParentWithChild(); new Child(parent); // sets parent.Child
...
나는 방금 SE가 주관적인 질문을 허용하지 않으며 이것이 주관적인 질문이라는 것을 배웠습니다. 그러나 아마도 좋은 주관적인 질문 일 것입니다.