Çok sayıda farklı ebeveyn / çocuk sınıfı olan bir nesne modeli geliştiriyorum. Her alt nesnenin üst nesnesine bir başvurusu vardır. Ana referansı başlatmak için birkaç yol düşünebilirim (ve denedim), ancak her yaklaşımın önemli dezavantajlarını buldum. Aşağıda açıklanan yaklaşımlar göz önüne alındığında hangisi en iyisidir ... veya hangisi daha iyidir.
Aşağıdaki kodun derlendiğinden emin olamayacağım, bu yüzden kod sözdizimsel olarak doğru değilse lütfen niyetimi görmeye çalışın.
Her zaman göstermesem de, alt sınıf yapıcılarımın bazılarının (ebeveyn dışında) parametre aldığını unutmayın.
Arayanın ebeveyni ayarlamaktan ve aynı ebeveyne eklemekten sorumludur.
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;} } }
Dezavantajı: ana ayarlama tüketici için iki aşamalı bir işlemdir.
var child = new Child(parent); parent.Children.Add(child);
Olumsuz: hata eğilimli. Arayan, çocuğu başlatmak için kullanılandan farklı bir ebeveyne çocuk ekleyebilir.
var child = new Child(parent1); parent2.Children.Add(child);
Ebeveyn, arayanın başlatıldığı ebeveyn için çocuğu eklediğini doğrular.
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); } }
Dezavantajı: Arayanın ebeveyn ayarlamak için hala iki aşamalı bir süreci var.
Dezavantajı: çalışma zamanı kontrolü - performansı düşürür ve her ekleme / ayarlayıcıya kod ekler.
Çocuk, ebeveyne eklendiğinde / atandığında ebeveyn, çocuğun ebeveyn referansını (kendisine) ayarlar. Üst ayarlayıcı dahilidir.
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); } }
Dezavantajı: Çocuk ebeveyn referansı olmadan yaratılır. Bazen başlatma / doğrulama ebeveyn gerektirir, bu da bazı başlangıç / doğrulama işlemlerinin çocuğun ebeveyn belirleyicisinde yapılması gerektiği anlamına gelir. Kod karmaşıklaşabilir. Çocuğun ebeveyni referansı olsaydı, çocuğu uygulamak çok daha kolay olurdu.
Ebeveyn, fabrika ekleme yöntemlerini gösterir; böylece bir çocuğun her zaman ebeveyn referansı olur. Çocuk oyuncağı dahilidir. Üst ayarlayıcı özeldir.
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; } }
Olumsuz: gibi başlatma sözdizimi kullanamazsınız
new Child(){prop = value}
. Bunun yerine yapmak zorunda:var c = parent.AddChild(); c.prop = value;
Dezavantajı: Fabrika yapıcı yöntemlerde alt yapıcı parametrelerini çoğaltmanız gerekir.
Dezavantajı: Bekar bir çocuk için mülk ayarlayıcısı kullanılamaz. Değeri belirlemek için bir yönteme ihtiyacım var, ancak özellik alıcı aracılığıyla okuma erişimi sağlıyor gibi görünüyor. Dengesiz.
Alt yapıda başvurulan üst öğeye kendisini ekler. Çocuk bakıcısı halka açıktır. Genel, üst öğeden erişim eklemedi.
//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;} } }
Olumsuz: arama sözdizimi çok iyi değil. Normalde biri
add
, yalnızca bunun gibi bir nesne oluşturmak yerine, üst öğe üzerinde bir yöntem çağırır :var parent = new ParentWithChildren(); new Child(parent); //adds child to parent new Child(parent); new Child(parent);
Ve böyle bir nesne oluşturmak yerine bir özellik ayarlar:
var parent = new ParentWithChild(); new Child(parent); // sets parent.Child
...
SE'nin bazı subjektif sorulara izin vermediğini ve açıkça bu subjektif bir soru olduğunu öğrendim. Ama belki de bu öznel bir sorudur.