ออกแบบ: โทรกลับไปที่ชั้นผู้ปกครอง


13

เมื่อสร้างแบบจำลองวัตถุกับเด็ก ๆ เป็นเรื่องปกติที่จะรวมเด็ก ๆ ผ่านการจัดองค์ประกอบในฐานะสมาชิกของชั้นผู้ปกครอง บางครั้งเด็ก ๆ ต้องบอกบางสิ่งกับผู้ปกครองพวกเขาจำเป็นต้องเรียกใช้ฟังก์ชันของผู้ปกครอง วิธีนี้สามารถทำได้โดยใช้ C ++ ตัวเลือกบางอย่างคือ:

  1. ทำให้คลาส parent ระดับโลกดังนั้นวัตถุลูกจะสามารถเรียกฟังก์ชันสมาชิกของวัตถุแม่ได้

  2. ฉีดวัตถุแม่เป็นตัวชี้หรือการอ้างอิงลงในวัตถุลูกทุก จากนั้นเมื่อเด็กต้องการบอกวัตถุแม่บางอย่างก็สามารถทำได้เพราะมันมีตัวแปรสมาชิกที่สามารถใช้

วิธีอื่นในการทำเช่นนี้คืออะไร? มีลวดลายหรือชื่อการออกแบบทั่วไปสำหรับสิ่งนี้หรือไม่?

โปรดทราบว่าฉันสนใจในแนวคิดและวิธีแก้ปัญหาใน C ++ เนื่องจากรายละเอียดจะแตกต่างกันในภาษาเชิงวัตถุอื่น ๆ ตัวอย่างเช่นจุดที่ 2 ด้านบนกล่าวถึง 'ตัวชี้หรือการอ้างอิง' และทั้งสองจะเป็นไปได้ใน C ++ เท่านั้น C ++ มีฟีเจอร์ภาษาที่ไม่ปรากฏในภาษาอื่นดังนั้นการใช้งานโซลูชันเพื่อแก้ไขปัญหาอาจรวมฟีเจอร์ภาษาเหล่านี้ซึ่งทำให้โซลูชันแตกต่างจากสิ่งที่อาจมีในภาษาอื่น


คุณสามารถเพิ่มตัวอย่างได้หรือไม่ นี่เป็นตัวอย่างที่ถูกต้องสำหรับคำถามของคุณหรือไม่ คุณมี orderobject (= พาเรนต์) พร้อม orderitems (children) และต้องการอัปเดตผลรวมการสั่งซื้อเมื่อมีการเปลี่ยนแปลงปริมาณ orderitem หรือกำลังคิดถึงบางสิ่งที่แตกต่างอย่างสิ้นเชิง?
k3b

@ k3b ใช่นั่นเป็นตัวอย่างที่ถูกต้อง ข้อมูลบางอย่างในเด็กเปลี่ยนไปทำให้ผู้ปกครองต้องทำอะไรบางอย่าง
sashang

เพียงเพิ่มพารามิเตอร์คอนสตรัคเตอร์และอ้างอิงสมาชิกข้อมูลไปยังคลาสย่อยแต่ละคลาส
tp1

เด็กจำเป็นต้องรู้ทุกอย่างเกี่ยวกับผู้ปกครองหรือว่าเรียบง่ายdelegateพอเพียงหรือไม่?
Julien Guertault

คำตอบ:


16

สิ่งแรกสิ่งนี้อาจเป็นกลิ่นรหัส จุดประสงค์ของการใช้องค์ประกอบสำหรับผู้ปกครอง / เด็กคือผู้ปกครองรู้เกี่ยวกับเด็ก แต่ไม่กลับกัน โดยเฉพาะอย่างยิ่งถ้าความสัมพันธ์นั้นมากกว่า 'ประกอบด้วย' มากกว่า 'ประกอบด้วย'

การอ้างอิงถึงพาเรนต์เป็นไปได้และค่อนข้างธรรมดาใน C ++ ในภาษาอื่น ๆ มักใช้ฟังก์ชั่นวัตถุหรือเหตุการณ์เพื่อให้เด็กสื่อสารสิ่งที่บุคคลภายนอกอาจต้องการทราบ นี่เป็นรูปแบบการเผยแพร่ - สมาชิกทั่วไป ฉันสงสัยว่าสำนวนใดที่มากกว่านั้นขึ้นอยู่กับเวอร์ชัน C ++ ที่คุณใช้และมาตรฐานของ codebase ของคุณ


ในสถานการณ์ของฉันมันเป็นกลิ่นรหัส คำตอบที่ดี
Martin Pfeffer

3

ตามที่คนอื่น ๆ ได้ชี้ให้เห็นความคิดพื้นฐานของการฉีดวัตถุแม่เป็นตัวชี้หรือการอ้างอิงเป็นวิธีที่จะไป - ในหลักการ

สิ่งนี้มีข้อเสียเปรียบหนึ่งข้อ: คุณจะได้รับการพึ่งพาแบบวนรอบระหว่างผู้ปกครองกับเด็ก หากคุณต้องการหลีกเลี่ยงปัญหานั้นให้นิยามคลาสฐานนามธรรม (อินเตอร์เฟส) IParentซึ่งพาเรนต์ของคุณสืบทอด IParentควรมีวิธีการเป็นฟังก์ชั่นเสมือนที่เด็กต้องการที่จะเรียก IParentจากนั้นฉีดแม่ที่อ้างอิงถึง สิ่งนี้ทำให้หน่วยทดสอบเด็กง่ายขึ้นมากตั้งแต่ตอนนี้คุณสามารถแทนที่วัตถุแม่ได้อย่างง่ายดายด้วยวัตถุจำลอง

ถ้าลูกของคุณต้องการเรียกใช้เพียงหนึ่งฟังก์ชันของวัตถุพาเรนต์IParentคลาสที่สมบูรณ์อาจมีขนาดใหญ่เกินไป ในกรณีนี้มันจะเพียงพอที่จะฉีดตัวชี้ไปยังฟังก์ชันสมาชิกลงในเด็กหรือวัตถุ functor encapsulating ฟังก์ชันสมาชิกนั้น


2

สิ่งที่คุณสามารถทำได้คือเก็บการอ้างอิงถึงผู้ปกครองในชั้นเรียนของเด็กโดยเรียงตาม ด้วยวิธีนี้เด็กรู้จักพ่อแม่ของเขาและสามารถเรียกใช้วิธีการสาธารณะในนั้น

ดังนั้นฉันจะไปกับตัวเลือก 2 คุณต้องระวังแม้ว่าเมื่อเด็กถูกลบออกจากผู้ปกครองคุณจะต้องลบการอ้างอิงถึงผู้ปกครองในเด็กและชี้ไปที่ null (หรือผู้ปกครองใหม่ถ้าเขามี หนึ่ง). หรือคุณสามารถลบวัตถุลูกได้โดยขึ้นอยู่กับบริบท


1

ส่งต่อการอ้างอิงหรือตัวชี้ไปยังผู้ปกครอง คุณสามารถทำให้พวกเขาเป็นเพื่อนกับผู้ปกครองหรือทำให้วิธีการที่เรียกว่าสาธารณะ หากคุณไม่ต้องการทำสิ่งใด ๆ ข้างต้นคุณสามารถส่งผ่านวัตถุ "สะพาน" ซึ่งเปิดเผยวิธีการของผู้ปกครองอย่างใดอย่างหนึ่งในที่สาธารณะและเป็นชั้นเรียนที่ซ้อนทับกันของผู้ปกครอง (ดังนั้นจึงสามารถเข้าถึงวิธีการผู้ปกครองทุกคน ) อย่างไรก็ตามมันอาจซับซ้อนเกินไปในหลาย ๆ สถานการณ์


1

2) ฉีดวัตถุแม่เป็นตัวชี้หรือการอ้างอิงลงในวัตถุลูกทุก จากนั้นเมื่อเด็กต้องการบอกวัตถุแม่บางอย่างก็สามารถทำได้เพราะมันมีตัวแปรสมาชิกที่สามารถใช้

เป็นตัวเลือกที่ทำงานได้อย่างสมบูรณ์แบบ ภาษาสมัยใหม่ทั้งหมดมีคุณสมบัติที่สามารถใช้อ้างอิงภาษาอื่น


1

มีวิธีการคล้ายกับการเปลี่ยนแปลงเล็กน้อย แต่ให้ข้อดี:

บอกว่าผู้ปกครอง A มีส่วนประกอบ C

ใน Component C ให้ประกาศ InterfaceC และอ้างอิงค้างไว้ นี่คือส่วนต่อประสานของส่วนประกอบกับโลกภายนอก

Parent A ดำเนิน InterfaceC และตั้งค่าการอ้างอิงใน Component C Component C เห็น Parent A เป็น InterfaceC

แนวคิดคือ: องค์ประกอบพูดคุยกับภายนอกโดยใช้ส่วนต่อประสาน

ข้อดีของการใช้สิ่งนี้มากกว่าการตั้งค่าพาเรนต์โดยตรงคือ:

สมมติว่าส่วนประกอบทำบางสิ่งบางอย่างและจำเป็นต้องแจ้งให้ผู้ปกครองทราบ มันเรียกอินเตอร์เฟซ ในภายหลังคุณตัดสินใจว่าคุณต้องการเปลี่ยนพาเรนต์ องค์ประกอบไม่สนใจเลยและคุณจะไม่ทำการเปลี่ยนแปลงใด ๆ

พูดในภายหลังว่าคุณต้องการแจ้งให้หลาย ๆ วัตถุของเหตุการณ์ทราบ คุณเพียงแค่สร้างรายการของ InterfaceC และเพิ่มการอ้างอิงถึงมัน

ข้อเสีย: คลาสผู้ปกครองจะจบลงด้วยการใช้อินเทอร์เฟซมากมาย (ฉันคิดว่านี่เป็นข้อได้เปรียบเนื่องจากตั้งแต่ดูประกาศคลาสฉันรู้ทันทีว่าใครพูดถึงมัน)


0

หมายเหตุนี่คือ c # เฉพาะ ฉันไม่ทราบว่า c ++ มีบางอย่างที่คล้ายกันหรือไม่

หากคุณมี GUI ฟอร์มพร้อมปุ่มกดที่คุณมักจะมีวิธีการที่แตกต่างกันโดยใช้เหตุการณ์ subscribtionยังเป็นที่รู้จักObserver_patternหรือเผยแพร่สมัครรูปแบบ

ปุ่มกดมักจะไม่รู้รูปแบบเฉพาะที่มันอยู่ ปุ่มจะทริกเกอร์หรือเผยแพร่เหตุการณ์และแบบฟอร์มจะได้รับการแจ้งเตือนที่สมัครเป็นสมาชิกและสามารถตอบสนองได้

ข้างๆ gui-s กลไกนี้สามารถใช้ได้ในทุกความสัมพันธ์แบบพ่อ - แม่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.