OOP: อะไรคือสถานการณ์บางอย่างที่การออกแบบโดยใช้คลาสดีกว่าอินเตอร์เฟสที่ใช้


10

ผมอ่าน เว็บไซต์ของ JDOM

ทำไม JDOM API จึงถูกกำหนดในรูปแบบของคลาสที่เป็นรูปธรรมมากกว่าส่วนต่อประสาน?

Jason Hunter สรุปข้อโต้แย้งกับ API ที่ใช้อินเตอร์เฟสสำหรับ JDOM:

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

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

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

อาจจะใช้คลาสคอนกรีตที่เหมาะสมในบางสถานที่ มีปัญหาของคลาสทั่วไปที่ใช้คลาสคอนกรีตในการออกแบบไม่เป็นไร


คุณอาจต้องการดูที่นี้: javaworld.com/javaworld/jw-09-2001/jw-0921-interface.html
NoChance

นอกจากนี้คุณยังสามารถดูซีรี่ส์ "จำกัด นามธรรมของคุณ": ayende.com/blog/153889/…
henginy

"เราทำได้และการออกแบบก็ดีกว่ามาก" - มันเป็นยังไงดี
CodeART

คำตอบ:


6
  • การสืบทอดสร้างการพึ่งพาการใช้งานซึ่งอาจเป็นปัญหาใหญ่เกี่ยวกับการบำรุงรักษา ข้อสรุปของเรื่องนี้คือคุณสามารถใช้การสืบทอดและคลาสที่เป็นรูปธรรมได้อย่างปลอดภัยเมื่อจัดการกับออบเจ็กต์การถ่ายโอนข้อมูลซึ่งโดยนิยามแล้วแทบไม่มีการใช้งาน คุณยังสามารถใช้การสืบทอดคลาสที่เป็นรูปธรรมเมื่อคุณต้องการการพึ่งพานี้ คุณอาจต้องการใช้คลาสนามธรรมที่มีเมธอดทั่วไป (โดยทั่วไปคือฟังก์ชันยูทิลิตี้) ที่ด้านบนของลำดับชั้นในสถานการณ์นี้
  • เมื่อใช้ลำดับชั้นคอนกรีตไม่ลืมที่จะใช้Liskov ชดเชยหลักการ
  • ไม่มีปัญหากับการใช้คลาสที่เป็นรูปธรรมสำหรับไคลเอนต์ (เช่นคลาสที่ใช้ไม่ใช่คลาสที่ใช้)
  • IMHO คุณสามารถใช้คลาสที่เป็นรูปธรรมจนกว่าจะมีสิ่งเปลี่ยนแปลง เปิด / ปิดหลักการ จะบอกให้คุณใช้อินเตอร์เฟซที่จะหลีกเลี่ยงการมีเพศสัมพันธ์ แต่เกี่ยวกับคุณไม่ gonna จำเป็นต้องใช้หลักการคุณอาจพิจารณาใช้การเรียนคอนกรีตจนถึงขณะนี้เมื่อคุณต้องการบางสิ่งบางอย่างเปลี่ยนแปลงในการดำเนินการ ปัญหาคือคุณจะต้องเปลี่ยนไคลเอนต์ของคลาสทั้งหมดของคุณในครั้งแรกที่มีการเปลี่ยนแปลงบางสิ่งบางอย่าง ในขณะที่คุณมีเครื่องมือเดียวที่สามารถทำได้บางอย่างคุณสามารถใช้คลาส IMO ที่เป็นรูปธรรมได้

[แก้ไข] เว็บไซต์ของ JDOM ใช้ java.io.File เป็นตัวอย่าง แต่นี่เป็นการออกแบบโดยใช้ส่วนต่อประสานเป็นหนึ่งสามารถจัดการกับอินสแตนซ์ java.io.File ราวกับว่ามันเป็น Serializable เท่านั้น ในสถานการณ์นี้มีเพียง "ผู้สร้าง" เท่านั้นที่จะรู้ระดับที่เป็นรูปธรรม


มีคำจำกัดความที่ขัดแย้งกันสองประการของ "วัตถุค่า" ลอยอยู่รอบ ๆ คุณดูเหมือนจะเป็นคนธรรมดาน้อยกว่าที่รู้จักกันว่า "วัตถุการถ่ายโอนข้อมูล"
Michael Borgwardt

@MichaelBorgwardt ขอบคุณสำหรับการชี้ออกมานี้เป็นฉันไม่ได้หมายความว่า "การถ่ายโอนข้อมูลวัตถุ" เท่านั้น: ฉันแก้ไขคำตอบของฉัน
แมทเธีย Jouan

1
LSP เป็นสิ่งสำคัญสำหรับการใด ๆความสัมพันธ์ subtyping, ใช้อินเตอร์เฟซเช่นเดียวกับมรดก

3

จากเว็บไซต์ JDOM:

Jason (Hunter) ก่อตั้งโครงการ JDOM ในช่วงต้นปี 2000 พร้อมกับ Brett McLaughlin

นั่นคือประมาณเวลาที่ Java 1.3 ถูกเปิดตัว ไม่มีอะไรในความเป็นผู้ใหญ่เมื่อมาถึงการพัฒนา Java - นักพัฒนาที่มีประสบการณ์มากที่สุดมีเพียง 4 ปีที่ใช้ Java อย่างดีที่สุด ไม่มีคอนเทนเนอร์ IoC ที่ใช้กันอย่างแพร่หลายไม่มีไฮเบอร์เนต Apache Struts เพิ่งเริ่มต้น

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

พวกเขาผิดอย่างแน่นอนเกี่ยวกับ

สิ่งใดก็ตามที่สามารถทำได้ด้วยส่วนต่อประสานสามารถทำได้ด้วย subclassing

Java ไม่อนุญาตให้มีการสืบทอดคลาสหลายคลาส แต่อนุญาตการใช้งานหลายอินเตอร์เฟส ที่สามารถสร้างความแตกต่างที่แท้จริง


3

โปรดจำไว้ว่าเกี่ยวกับคำถามของคุณว่าในการพัฒนาซอฟต์แวร์มีหลายวิธีในการแก้ปัญหาและหากนักพัฒนาซอฟต์แวร์บางรายใช้เทคนิคที่แตกต่างจากของคุณนั่นไม่ได้หมายความว่าการแก้ปัญหาจะผิด

หนึ่งในนั้นคือ "อินเทอร์เฟซ" กับ (คลาส) "คลาส" มีสถานการณ์ที่สามารถบรรลุเป้าหมายเดียวกันได้ทั้งสองเทคนิค

เพื่อให้สิ่งต่าง ๆ มีความซับซ้อนมากขึ้นมีการใช้อินเทอร์เฟซหลายอย่างที่ต้องพูดถึง:

  • หนึ่งคือการออกแบบ "สัญญา" หรือ "สเปค" โดยไม่ต้อง "การใช้งาน"
  • อื่น ๆ เพื่อเพิ่มฟังก์ชันการทำงานให้กับคลาสที่มีอยู่ไม่ใช่คลาสใหม่หรือลำดับชั้นของคลาส
  • ประกอบกับก่อนหน้านี้เพื่ออนุญาตให้ใช้งานร่วมกันระหว่างออบเจ็กต์เทคโนโลยีที่แตกต่างกันตัวอย่างเช่น Enterprise Beans, CORBA, COM, WebServices
  • เพื่อเลียนแบบหลายมรดก

คำถามของคุณใช้กับจุดแรก

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

และออกจากอินเตอร์เฟสสำหรับสถานการณ์อื่น ๆ

ตัวอย่างที่ดีคือไลบรารีวิดเจ็ต (คอนโทรล)

ฉันขอแนะนำให้ดูที่ภาษาโปรแกรมอื่น ๆ พวกเขาใช้อินเตอร์เฟสและคลาสเช่น: PHP, Delphi (Object Pascal), C # ได้อย่างไร

ไชโย


1

กฎการออกแบบ API เป็นสิ่งที่เฉพาะเจาะจงจริงๆ ฉันไม่แน่ใจว่าคุณควรสรุปอะไรจากคำถามที่พบบ่อยในแง่ของวิธีการออกแบบรหัสประจำวันของคุณ

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

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

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


0

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

ดังนั้นหากเรากำลังมองหาชั้นเรียนที่เราไม่เคยผ่านรอบยกเว้นปกติฤดูใบไม้ผลิที่ใจ ฉันไม่ใช่นักพัฒนา Java แต่แน่นอนในภาษาอื่นที่คล้ายคลึงกันฉันไม่คิดว่าฉันเคยเห็นอินเตอร์เฟสที่กำหนดไว้สำหรับข้อยกเว้น

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