เหตุใดจึงกำหนดวัตถุ Java โดยใช้ส่วนต่อประสาน (เช่นแผนที่) แทนที่จะใช้งาน (HashMap)


17

ในรหัส Java ส่วนใหญ่ฉันเห็นคนประกาศวัตถุ Java เช่นนี้:

Map<String, String> hashMap = new HashMap<>();
List<String> list = new ArrayList<>();

แทน:

HashMap<String, String> hashMap = new HashMap<>();
ArrayList<String> list = new ArrayList<>();

ทำไมจึงมีการตั้งค่าเพื่อกำหนดวัตถุ Java โดยใช้อินเตอร์เฟซมากกว่าการใช้งานที่จะใช้จริง?


คำตอบ:


26

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

ควรกล่าวว่ามีข้อยกเว้นนี้เมื่อมีการใช้งานมีความเกี่ยวข้อง หากคุณต้องการแผนที่เมื่อคำสั่งซื้อมีความสำคัญคุณสามารถกำหนดให้ a TreeMapหรือ a LinkedHashMapเพื่อผ่านหรือดีกว่าSortedMapซึ่งยังไม่ได้ระบุการใช้งานเฉพาะ สิ่งนี้ทำให้ผู้เรียกต้องผ่านการใช้งานแผนที่บางประเภทและคำแนะนำอย่างยิ่งว่าคำสั่งซื้อนั้นมีความสำคัญ ที่กล่าวว่าคุณสามารถแทนที่SortedMapและผ่านหนึ่งไม่ได้เรียง? ใช่แน่นอนอย่างไรก็ตามคาดว่าสิ่งเลวร้ายจะเกิดขึ้น

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


เมื่อคุณต้องการแผนที่ที่เรียงพิมพ์พารามิเตอร์ที่ควรจะเป็นไม่ได้SortedMap TreeMap
Cephalopod

@Arian SortedMapเป็นหนึ่งในการนำไปใช้งานหลายอย่างที่เกี่ยวข้องกับการสั่งซื้อ นั่นคือนอกเหนือจากจุด TreeMapยังสั่งรายการตามการใช้งานที่สำคัญของComparableหรือได้รับComparatorอินเตอร์เฟซ
Neil

ไม่ SortedMap ไม่ใช่การติดตั้งนั่นคือประเด็น มันเป็นอินเทอร์เฟซสำหรับแผนที่ที่เรียงลำดับตามคีย์
Cephalopod

1
@Arian Ah ฉันเห็นสิ่งที่คุณหมายถึง จริงแล้ว SortedMap ที่ดีกว่านั้นไม่ได้บังคับให้ใช้งาน ฉันจะทำการปรับเปลี่ยนที่เหมาะสม
Neil

ที่จริงไม่ใช้LinkedHashMap SortedMapsubclasses ของเดียวของSortedMapเป็นและConcurrentSkipListMap TreeMap
bcorso

10

ในคำพูดของคนธรรมดา:

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

โดยใช้ปลั๊กมาตรฐานพวกเขาอนุญาตให้เสียบ apliance เดียวกันในปลั๊กใด ๆ ที่เข้ากันได้รอบบ้าน

จากมุมมองของเต้ารับบนผนังมันไม่สำคัญว่าคุณจะเสียบทีวีหรือสเตอริโอ

สิ่งนี้ทำให้ทั้งเครื่องและซ็อกเก็ตมีประโยชน์มากขึ้น

ยกตัวอย่างวิธีการที่ยอมรับแผนที่เป็นอาร์กิวเมนต์

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

นั่นคือหลักการทดแทน Liskov

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

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


4

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

ตัวอย่างเช่นหากคุณต้องการทราบภายหลังคุณต้องการ a จริง ๆLinkedHashMapคุณสามารถทำการเปลี่ยนแปลงนั้นอย่างปลอดภัยโดยไม่ส่งผลกระทบต่อโค้ดอื่น ๆ

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


3

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

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

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

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