ฉันกำลังพัฒนาโมเดลวัตถุที่มีคลาสแม่ / ลูกที่แตกต่างกันจำนวนมาก แต่ละวัตถุลูกมีการอ้างอิงถึงวัตถุแม่ของมัน ฉันสามารถนึกถึง (และลอง) หลายวิธีในการเริ่มต้นการอ้างอิงผู้ปกครอง แต่ฉันพบข้อบกพร่องที่สำคัญสำหรับแต่ละวิธี ให้แนวทางที่อธิบายไว้ด้านล่างซึ่งดีที่สุด ... หรือสิ่งที่ดียิ่งขึ้น
ฉันจะไม่ตรวจสอบว่ารหัสด้านล่างรวบรวมดังนั้นโปรดลองดูความตั้งใจของฉันถ้ารหัสไม่ถูกต้อง syntactically
โปรดทราบว่าตัวสร้างคลาสลูกของฉันบางคนใช้พารามิเตอร์ (นอกเหนือจากแม่) แม้ว่าฉันจะไม่แสดงใด ๆ
ผู้เรียกมีหน้าที่ตั้งค่าพาเรนต์และเพิ่มในพาเรนต์เดียวกัน
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;} } }
ข้อเสีย:การตั้งค่าพาเรนต์เป็นกระบวนการสองขั้นตอนสำหรับผู้ใช้บริการ
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); } }
ข้อเสีย:ผู้โทรยังคงมีกระบวนการสองขั้นตอนสำหรับการตั้งค่าพาเรนต์
ข้อเสีย: การตรวจสอบรันไทม์ - ลดประสิทธิภาพและเพิ่มรหัสให้กับทุก ๆ การเพิ่ม / setter
ผู้ปกครองตั้งค่าการอ้างอิงผู้ปกครองของเด็ก (กับตัวเอง) เมื่อมีการเพิ่ม / กำหนดเด็กให้กับผู้ปกครอง Parent Setter เป็นภายใน
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 อยู่ภายใน แม่ Setter เป็นส่วนตัว
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;
ข้อเสีย:ต้องทำซ้ำพารามิเตอร์ของตัวสร้างลูกในวิธีการเพิ่มจากโรงงาน
ข้อเสีย:ไม่สามารถใช้ setter คุณสมบัติสำหรับชายน์เดี่ยว ดูเหมือนง่อยที่ฉันต้องการวิธีการตั้งค่า แต่ให้เข้าถึงการอ่านผ่านตัวรับทรัพย์สิน มันลำเอียง
เด็กเพิ่มตัวเองให้กับผู้ปกครองที่อ้างอิงในตัวสร้างของมัน เด็ก 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 ไม่อนุญาตให้มีคำถามแบบอัตนัยและชัดเจนว่านี่เป็นคำถามแบบอัตนัย แต่อาจเป็นคำถามอัตนัยที่ดี