ฉันอ่านเกี่ยวกับรูปแบบการออกแบบและฉันอ่านว่ารูปแบบการออกแบบต้นแบบนั้นมีซับคลาสที่มากเกินไป
ทำไมการแบ่งคลาสย่อยไม่ดี การใช้ต้นแบบจะได้ประโยชน์อะไรจากการทำ subclassing
ฉันอ่านเกี่ยวกับรูปแบบการออกแบบและฉันอ่านว่ารูปแบบการออกแบบต้นแบบนั้นมีซับคลาสที่มากเกินไป
ทำไมการแบ่งคลาสย่อยไม่ดี การใช้ต้นแบบจะได้ประโยชน์อะไรจากการทำ subclassing
คำตอบ:
ทำไมการแบ่งคลาสย่อยมากเกินไปจึงไม่ดี
"มากเกินไป" เป็นคำพิพากษา แต่เอาไปจากฉันมันไม่ดี รหัสที่ฉันทำงานด้วยมีการสืบทอด DEEP และรหัสนั้นยากที่จะอ่านทำความเข้าใจติดตามติดตามตรวจแก้จุดบกพร่อง ฯลฯ ฯลฯ เป็นไปไม่ได้ที่จะเขียนโค้ดทดสอบสำหรับสิ่งนี้ได้อย่างมีประสิทธิภาพ
รูปแบบต้นแบบทำไปด้วย subclassing
หรือคำถามนั้นหมายความว่า "มีคลาสย่อยมากเกินไปหรือไม่" รูปแบบนี้เรียกใช้การโคลนวัตถุ "เทมเพลต" เพื่อหลีกเลี่ยงการทำคลาสย่อยอย่างน้อยตอนนี้ ไม่มีกฎที่ระบุว่า "เทมเพลต" ไม่สามารถเป็นคลาสย่อยได้
ชอบองค์ประกอบมากกว่ามรดก
แนวคิดนี้รวมถึงการมอบหมายและการรวม การติดตามความรู้นี้หมายถึงซอฟต์แวร์ของคุณมีความยืดหยุ่นมากขึ้นง่ายต่อการบำรุงรักษาขยายและนำกลับมาใช้ใหม่
เมื่อระดับประกอบด้วยชิ้นส่วนที่คุณสามารถใช้แทนชิ้นส่วนเหล่านั้นที่รันไทม์ สิ่งนี้มีผลอย่างลึกซึ้งต่อความสามารถในการทดสอบ
การทดสอบเป็นเรื่องง่าย คุณสามารถใช้ชิ้นส่วนปลอม (เช่น "mocks", "คู่" และพูดคุยการทดสอบอื่น ๆ ) การสืบทอดทางลึกของรหัสของเราหมายความว่าเราต้องยกตัวอย่างลำดับชั้นทั้งหมดเพื่อทดสอบบิตใด ๆ ของมัน ในกรณีของเราที่เป็นไปไม่ได้หากไม่มีรหัสในสภาพแวดล้อมจริง ตัวอย่างเช่นเราต้องการฐานข้อมูลเพื่อยกตัวอย่างวัตถุทางธุรกิจ
การเปลี่ยนแปลงมาพร้อมกับผลข้างเคียงและความไม่แน่นอน - ยิ่ง "ฐาน" ชั้นเรียนยิ่งมีเอฟเฟ็กต์ที่แพร่หลายมากขึ้นสำหรับดีหรือไม่ดี อาจมีการเปลี่ยนแปลงที่คุณไม่กล้าทำเนื่องจากมีผลข้างเคียงที่ไม่แน่นอน หรือการเปลี่ยนแปลงที่ดีสำหรับสถานที่บางแห่งในห่วงโซ่มรดกของเราไม่ดีสำหรับคนอื่น นี่เป็นประสบการณ์ของฉันอย่างแน่นอน
ฉันคิดว่าหนึ่งในเหตุผลนี้ถูกมองว่าเป็นการปฏิบัติที่ไม่ดีคือเมื่อเวลาผ่านไปแต่ละคลาสย่อยสามารถมีคุณลักษณะและวิธีการที่ไม่สมเหตุสมผลสำหรับวัตถุนั้นยิ่งคุณลงไปในสายโซ่ (ในลำดับชั้นที่พัฒนาไม่ดี) คุณสามารถจบด้วยชั้นป่องที่มีรายการที่ไม่สมเหตุสมผลสำหรับชั้นเรียนนั้น
ฉันไม่เชื่อเรื่องนี้เลย ดูเหมือนว่าดื้อรั้นที่จะบอกว่ามันไม่ดี มีอะไรไม่ดีเมื่อนำไปใช้ในทางที่ผิด
ด้วยเหตุผลสองประการ
เป็นประสิทธิภาพรันไทม์ ทุกครั้งที่คุณเรียกใช้คลาสย่อยจากซูเปอร์คลาสที่คุณกำลังเรียกใช้เมธอดดังนั้นหากคุณมีคลาสที่ซ้อนกันห้าคลาสและเรียกใช้เมธอดในคลาสพื้นฐานคุณจะทำการเรียกใช้เมธอดห้าครั้ง คอมไพเลอร์ / รันไทม์ส่วนใหญ่จะพยายามจดจำสิ่งนี้และเพิ่มประสิทธิภาพการโทรพิเศษ แต่จะปลอดภัยเพียงการทำเช่นนี้สำหรับกรณีที่ง่ายมาก
คือความมีสติของโปรแกรมเมอร์เพื่อนคุณ หากคุณซ้อนห้าคลาสฉันต้องตรวจสอบคลาสแม่ทั้งสี่เพื่อสร้างว่าคุณกำลังเรียกวิธีการในคลาสพื้นฐานจริง ๆ มันน่าเบื่อ ฉันอาจต้องผ่านการเรียกใช้วิธีการถึงห้าครั้งเมื่อฉันดีบักโปรแกรม
"มากเกินไป" เป็นคำพิพากษา
เช่นเดียวกับสิ่งส่วนใหญ่ในการเขียนโปรแกรมการจัดกลุ่มย่อยนั้นไม่ได้เลวร้ายเมื่อมันสมเหตุสมผล เมื่อแบบจำลองของวิธีการแก้ปัญหาของคุณเหมาะสมกว่าเป็นลำดับชั้นมากกว่าองค์ประกอบของส่วนประกอบการจัดคลาสย่อยอาจเป็นตัวเลือกที่ต้องการ
ที่กล่าวว่าองค์ประกอบที่นิยมเหนือมรดกเป็นกฎง่ายๆ
เมื่อคุณคลาสย่อยการทดสอบอาจทำได้ยากขึ้น (ดังระบุ Radarbob ) ในลำดับชั้นลึกการแยกรหัสที่มีปัญหานั้นยากกว่าเนื่องจากการสร้างอินสแตนซ์ย่อยให้กับคลาสนั้นจะต้องนำลำดับชั้นของซูเปอร์คลาสทั้งหมดและรหัสเพิ่มเติม ด้วยวิธีการผสมผสานคุณสามารถแยกและทดสอบแต่ละส่วนประกอบของวัตถุรวมของคุณด้วยการทดสอบหน่วยวัตถุจำลอง ฯลฯ
การจัดคลาสย่อยสามารถทำให้คุณเปิดเผยรายละเอียดของการติดตั้งที่คุณอาจไม่ต้องการ สิ่งนี้ทำให้ยากต่อการควบคุมการเข้าถึงการแสดงข้อมูลพื้นฐานของคุณและเชื่อมโยงคุณกับการใช้งานแบบจำลองการสำรองข้อมูลของคุณโดยเฉพาะ
ตัวอย่างหนึ่งที่ฉันนึกได้คือ java.util.Properties ซึ่งสืบทอดมาจาก Hashtable คลาส Properties มีจุดประสงค์เพื่อเก็บคู่ String-String เท่านั้น (ซึ่งจะถูกบันทึกไว้ใน Javadocs) เนื่องจากการสืบทอดวิธีการ put และ putAll จาก Hashtable ได้ถูกเปิดเผยแก่ผู้ใช้ Properties ในขณะที่วิธีการ "ถูกต้อง" ในการจัดเก็บพร็อพเพอร์ตี้คือ setProperty () ไม่มีอะไรที่ขัดขวางผู้ใช้ในการเรียกใช้ put () และส่งผ่านสตริงและออบเจ็กต์
โดยทั่วไปความหมายของคุณสมบัติถูกกำหนดไว้ไม่ดีเนื่องจากการสืบทอด นอกจากนี้หากใครก็ตามต้องการเปลี่ยนวัตถุสำรองสำหรับคุณสมบัติผลกระทบจะมีผลกระทบมากขึ้นกับรหัสที่ใช้คุณสมบัติมากกว่าถ้าคุณสมบัติมีวิธีการจัดองค์ประกอบเพิ่มเติม
การสืบทอดสามารถทำลายการห่อหุ้มในบางกรณีและหากเกิดขึ้นมันจะไม่ดี อ่านเพิ่มเติม
ในวันเก่า ๆ ที่ไม่มีมรดกห้องสมุดจะเผยแพร่ API และแอปพลิเคชันที่ใช้มันทำให้สิ่งที่ปรากฏต่อสาธารณะและห้องสมุดมีวิธีจัดการกับอุปกรณ์ภายในที่มีการเปลี่ยนแปลงโดยไม่ทำลายแอป
เมื่อความต้องการวิวัฒนาการห้องสมุดสามารถพัฒนาและสามารถมีลูกค้าได้มากขึ้น หรือสามารถให้ฟังก์ชันการทำงานเพิ่มเติมโดยสืบทอดจากคลาสของตนเองกับรสชาติอื่น ๆ จนถึงตอนนี้ดีมาก
อย่างไรก็ตามสิ่งพื้นฐานคือถ้าแอปพลิเคชันใช้คลาสและเริ่มซับคลาสมันตอนนี้คลาสย่อยเป็นไคลเอนต์จริง ๆแทนที่จะเป็นคู่ค้าภายใน อย่างไรก็ตามแตกต่างจากวิธีที่ชัดเจนไม่ชัดเจนที่กำหนดเป็นสาธารณะ API, subclass ตอนนี้ลึกมากภายในห้องสมุด (การเข้าถึงตัวแปรส่วนตัวทั้งหมดและอื่น ๆ ) มันยังไม่เลว แต่ตัวละครที่น่ารังเกียจสามารถเชื่อม API ที่อยู่ภายในแอพและในห้องสมุด -
ในสาระสำคัญขณะนี้อาจไม่เป็นกรณี แต่
มันง่ายต่อการใช้มรดกเพื่อทำลาย encapsulation
การอนุญาตให้ subclassing อาจผิดถ้าจุดนั้น
คำตอบด่วนสั้น ๆ :
มันขึ้นอยู่กับสิ่งที่คุณกำลังทำ
คำตอบที่น่าเบื่อเพิ่มเติม:
ผู้พัฒนาสามารถสร้างแอปได้ ใช้ทั้งคลาสย่อยหรือแม่แบบ (ต้นแบบ) บางครั้งเทคนิคเดียวก็ใช้งานได้ดีกว่า บางครั้ง techinque อื่น ๆ ก็ทำงานได้ดีขึ้น
การเลือกใช้เทคนิคทำงานได้ดีที่สุดและต้องพิจารณาด้วยว่ามีหลายสถานการณ์ที่มีอยู่หรือไม่ แม้ว่าภาษาการเขียนโปรแกรมรองรับการสืบทอดเทมเพลตหรือต้นแบบเดียวเท่านั้น
หมายเหตุประกอบ:
บางคำตอบเกี่ยวข้องกับ "การสืบทอดหลายอย่าง" ไม่ใช่คำถามหลัก แต่เกี่ยวข้องกับหัวเรื่อง มีหลายโพสต์ที่คล้ายกันเกี่ยวกับ "หลายมรดกและองค์ประกอบ" ฉันมีกรณีที่ฉันผสมทั้งสอง