ควรใช้การสืบทอดเมื่อใดจึงจะใช้ 'เพียงฟิลด์บูลีน'


18

ในแอปพลิเคชัน Rails ของเราเรากำลังเพิ่มการแจ้งเตือน บางส่วนของสิ่งเหล่านี้คือblockingพวกเขาหยุดความคืบหน้าของทรัพยากรใด ๆ ที่พวกเขากำลังเพิ่มเพราะข้อมูลบางอย่างเกี่ยวกับทรัพยากรที่หายไป

การแจ้งเตือนอื่น ๆ เป็นการแจ้งเตือนที่ง่ายและให้ข้อมูลเท่านั้น

วันนี้ฉันได้พูดคุยกับโปรแกรมเมอร์คนอื่นในทีมของเรา ฉันได้สร้างโครงสร้างการสืบทอดเช่นนี้:

ป้อนคำอธิบายรูปภาพที่นี่

อย่างไรก็ตามเขาต้องการให้ฉันเพิ่มblockingวิธีการส่งคืนบูลีนในแต่ละการแจ้งเตือนและระบุรายการของคลาสย่อยที่ปิดกั้นภายในคลาสพาเรนต์การแจ้งเตือน

ความแตกต่างระหว่างวิธีการเหล่านี้ไม่มากนัก ในแนวทางของฉันไม่ต้องระบุรายการนี้ทำให้ root class cleaner ในทางตรงกันข้ามตรรกะพิเศษที่เกิดขึ้นในNotification::Blockingตอนนี้ก็ไม่ได้มีขนาดใหญ่มากเช่นกัน

นามธรรมชนิดใดที่เหมาะกับปัญหานี้มากขึ้น?


11
ชั้นปกครองไม่ควรรู้เกี่ยวกับมันเป็นลูก ทำไมคุณต้องการเก็บรายการของคลาสย่อย
coteyr

มีการเพิ่มทรัพยากรอย่างไรและจะหยุดความคืบหน้าได้อย่างไร
null

3
ทำไมคุณต้องมีคลาสการแจ้งเตือนมากมาย ฟังดูเหมือนว่าคุณจะสามารถสร้างคลาสการแจ้งเตือนหนึ่งคลาสจากนั้นให้ดาต้าดำเนินการแทนประเภทข้อมูล
ริป

1
@Trisped: ถูกต้องถ้าคุณพบว่าตัวเองกำลังเคลื่อนไหวด้านหนึ่งของพฤติกรรมไปสู่คลาสฐานพร้อมรายชื่อเคสอย่างละเอียดจากนั้นก็มีความกล้าหาญในความเชื่อมั่นของคุณยอมรับว่าคุณไม่ได้ออกแบบคลาสพื้นฐานที่ใช้งานได้ และย้ายพฤติกรรมทั้งหมดลงในคลาสฐาน!
Steve Jessop

คำตอบ:


35

คุณต้องการหลีกเลี่ยงคลาสพื้นฐานที่รู้เกี่ยวกับคลาสที่ได้รับ มันแนะนำการมีเพศสัมพันธ์แน่นและเป็นอาการปวดหัวบำรุงรักษาเพราะคุณต้องจำไว้ในการเพิ่มลงในรายการทุกครั้งที่คุณสร้างคลาสที่ได้รับใหม่

นอกจากนี้ยังจะป้องกันไม่ให้คุณสามารถใส่คลาสการแจ้งเตือนลงในแพ็คเกจ / ชุดประกอบที่สามารถใช้ซ้ำได้หากคุณต้องการใช้คลาสนี้ในหลายโครงการ

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


3
นี้. ตัดสินใจได้ในที่เดียว อย่ากระจายความรู้ที่คลาสบล็อกระหว่างคลาสและรายการ
candied_orange

นี่คือสิ่งที่ฉันทำทำงานได้ดีและสามารถนำกลับมาใช้ใหม่ได้มาก
coteyr

13

และระบุรายการของคลาสย่อยที่กำลังบล็อกภายในคลาสพาเรนต์การแจ้งเตือน

ที่ดูแปลกมากและมีกลิ่นรหัสโดยเฉพาะ

ฉันจะให้คลาสย่อยถ้าคุณมีความแตกต่างในพฤติกรรมระหว่างชั้นเรียนและคุณต้องการที่จะปฏิบัติกับการแจ้งเตือนเหล่านี้ทั้งหมดในแบบเดียวกัน (เช่นการใช้ความหลากหลาย )


1
ฉันคิดว่า "พฤติกรรม" เป็นกุญแจสำคัญที่นี่: เมื่อเป็นเพียงข้อมูลฟิลด์ควรเป็นตัวเลือกที่เพียงพอ พฤติกรรมเป็นเหตุผลที่ดีกว่าในการใช้ polymorphism แต่ก็ควรคำนึงถึงความซับซ้อนในการบำรุงรักษาเสมอเมื่อสร้างลำดับชั้นการสืบทอด อ่านen.wikipedia.org/wiki/Composition_over_inheritance
cottsak

7

ในฐานะที่เป็นคำตอบที่มีอยู่ผมขอแนะนำว่าคุณสมบัติบูลีนเป็นตัวเลือกที่ดีที่สุดหากจำเป็นต้องเปลี่ยนโหมดที่จะใช้แบบไดนามิก (เช่นผ่านไฟล์กำหนดค่าที่ให้รายการประเภทที่จะปิดกั้น และที่ไม่ได้)

ที่กล่าวว่าการออกแบบที่ดีขึ้นแม้ในสถานการณ์นี้อาจจะใช้วัตถุมัณฑนากร


1

ฉันจะบอกว่ามันขึ้นอยู่กับว่ามีอะไรพิเศษเป็นพิเศษเกี่ยวกับการแจ้งเตือนการปิดกั้นแม้ว่าความคิดแรกของฉันคือไปกับ "ทั้งสอง":

class Notification
 virtual Boolean Blocking{get return false;}

class BlockingNotification inherits Notification
 virtual overrides Boolean Blocking{get return true;}

ด้วยวิธีนี้คุณสามารถใช้n.Blockingหรือn is BlockingNotification(ทั้งหมดในรหัสหลอก) แม้ว่าถ้าคุณจะอนุญาตให้คลาสใช้ค่าตามบริบทที่มีความอ่อนไหวBlockingโดยดูว่าคุณจะต้องตรวจสอบค่านั้นทุกครั้งBlockingNotificationชั้นจะกลายเป็น มีประโยชน์น้อยกว่า

ในกรณีใด ๆ ฉันเห็นด้วยกับคำตอบอื่น ๆ ที่คุณไม่ต้องการให้การใช้คลาสพื้นฐานBlockingต้องรู้เกี่ยวกับคลาสที่ได้รับ


0

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

สิ่งนี้ช่วยให้คุณใช้รหัสหนึ่งชุดสำหรับการประมวลผลและการนำเสนอการแจ้งเตือนและลดความซับซ้อนของรหัสของคุณ

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