คลาสนามธรรมเทียบกับอินเตอร์เฟสใน Java


88

ฉันถูกถามคำถามฉันต้องการรับคำตอบของฉันตรวจสอบที่นี่

ถาม:ในสถานการณ์ใดที่เหมาะสมกว่าในการขยายคลาสนามธรรมมากกว่าการใช้อินเทอร์เฟซ

ตอบ:หากเราใช้รูปแบบวิธีการออกแบบเทมเพลต

ฉันถูกไหม ?

ขออภัยหากไม่สามารถระบุคำถามได้อย่างชัดเจน
ฉันรู้ความแตกต่างพื้นฐานระหว่างคลาสนามธรรมและอินเทอร์เฟซ

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

2) ใช้อินเทอร์เฟซหากคุณต้องการกำหนดลายเซ็นให้เหมือนกัน (และการนำไปใช้งานที่แตกต่างกัน) เพื่อให้คุณสามารถปฏิบัติตามการใช้งานอินเทอร์เฟซได้

3) เราสามารถขยายคลาสนามธรรมได้สูงสุดหนึ่งคลาส แต่สามารถใช้งานได้มากกว่าหนึ่งอินเทอร์เฟซ

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

อินเทอร์เฟซเทียบกับคลาสนามธรรม

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

เช่นเคยมีการปิด, อินเตอร์เฟซที่ช่วยให้คุณมีอิสระในเรื่องเกี่ยวกับชั้นฐานกับระดับนามธรรมจะช่วยให้คุณมีอิสระในการเพิ่มวิธีการใหม่ในภายหลัง - เอริชแกมมา

คุณไม่สามารถเปลี่ยนอินเทอร์เฟซได้โดยไม่ต้องเปลี่ยนสิ่งอื่น ๆ มากมายในโค้ดของคุณดังนั้นวิธีเดียวที่จะหลีกเลี่ยงปัญหานี้ได้คือการสร้างอินเทอร์เฟซใหม่ทั้งหมดซึ่งอาจไม่ใช่สิ่งที่ดีเสมอไป

Abstract classesควรใช้เป็นหลักสำหรับวัตถุที่เกี่ยวข้องอย่างใกล้ชิด Interfacesจะดีกว่าในการจัดหาฟังก์ชันการทำงานทั่วไปสำหรับคลาสที่ไม่เกี่ยวข้อง


สามารถทำซ้ำได้ของInterface vs Abstract Class (OO ทั่วไป)
bezmax


สิ่งนี้ไม่ซ้ำกัน OP ต้องการทราบว่าเมื่อใดควรขยายคลาสนามธรรมแทนที่จะใช้อินเทอร์เฟซ เขาไม่ต้องการรู้ว่าเมื่อใดควรเขียนคลาสนามธรรมหรืออินเทอร์เฟซ คลาสนามธรรมและอินเทอร์เฟซของเขาเขียนไว้แล้ว Hd ต้องการทราบว่าจะขยายหรือใช้งาน
Shiplu Mokaddim

1
@ shiplu.mokadd.im นั่นคือความแตกต่างที่ไม่มีความแตกต่าง คุณไม่สามารถใช้คลาสนามธรรมได้โดยไม่ต้องขยาย การไนท์พิคของคุณที่นี่ดูเหมือนไม่มีจุดหมายเลย
user207421

คำตอบ:


87

เมื่อจะใช้อินเทอร์เฟซ

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

เมื่อต้องการใช้คลาสบทคัดย่อ

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

เมื่อใดควรใช้ทั้งสองอย่าง

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


ฉันคิดว่า OP ต้องการทราบว่าเมื่อใดควรขยายคลาสนามธรรมแทนที่จะใช้อินเทอร์เฟซ
Shiplu Mokaddim

@ shiplu.mokadd.im จริงๆแล้ว OP ถามคำถามที่เฉพาะเจาะจงมากซึ่งคำตอบคือ 'ใช่' หรือ 'ไม่'
user207421

4
คุณถูก. แต่ดังนั้นเราจึงตอบใช่ / ไม่ใช่พร้อมคำอธิบายที่เหมาะสม
Shiplu Mokaddim

1
@ shiplu.mokadd.im ฉันไม่เห็นวิธีที่ให้ใบอนุญาตคุณในการระบุคำถามของเขาผิด
user207421

บนพื้นฐานของข้อความเดียวนี้If we are using template method design patternเราไม่สามารถพูดYESหรือNO
DivineDesert

31

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

ใช่ถ้าคุณใช้ JAXB ไม่ชอบอินเทอร์เฟซ คุณควรใช้คลาสนามธรรมหรือหลีกเลี่ยงข้อ จำกัด นี้ด้วยยาชื่อสามัญ

จากบล็อกโพสต์ส่วนตัว :

อินเตอร์เฟซ:

  1. คลาสสามารถใช้งานได้หลายอินเทอร์เฟซ
  2. อินเทอร์เฟซไม่สามารถให้รหัสใด ๆ ได้เลย
  3. อินเทอร์เฟซสามารถกำหนดค่าคงที่สุดท้ายแบบสาธารณะเท่านั้น
  4. อินเทอร์เฟซไม่สามารถกำหนดตัวแปรอินสแตนซ์ได้
  5. การเพิ่มวิธีการใหม่มีผลกระทบต่อการใช้คลาส (การบำรุงรักษาการออกแบบ)
  6. JAXB ไม่สามารถจัดการกับอินเทอร์เฟซได้
  7. อินเทอร์เฟซไม่สามารถขยายหรือใช้คลาสนามธรรมได้
  8. วิธีการเชื่อมต่อทั้งหมดเป็นแบบสาธารณะ

โดยทั่วไปควรใช้อินเทอร์เฟซเพื่อกำหนดสัญญา (สิ่งที่จะบรรลุไม่ใช่วิธีการบรรลุเป้าหมาย)

คลาสนามธรรม:

  1. ชั้นเรียนสามารถขยายนามธรรมได้สูงสุดหนึ่งคลาส
  2. คลาสนามธรรมสามารถมีรหัส
  3. คลาสนามธรรมสามารถกำหนดค่าคงที่ทั้งแบบคงที่และแบบอินสแตนซ์ (ขั้นสุดท้าย)
  4. คลาสนามธรรมสามารถกำหนดตัวแปรอินสแตนซ์
  5. การแก้ไขรหัสคลาสนามธรรมที่มีอยู่มีผลกระทบต่อการขยายคลาส (การบำรุงรักษาการนำไปใช้งาน)
  6. การเพิ่มวิธีการใหม่ในคลาสนามธรรมไม่มีผลกระทบต่อการขยายคลาส
  7. คลาสนามธรรมสามารถใช้อินเทอร์เฟซ
  8. คลาสนามธรรมสามารถใช้วิธีการส่วนตัวและได้รับการป้องกัน

ควรใช้คลาสบทคัดย่อสำหรับการนำไปใช้งาน (บางส่วน) สิ่งเหล่านี้สามารถเป็นตัวกำหนดวิธีการดำเนินการตามสัญญา API ได้


3
ใน Java 8 สำหรับอินเทอร์เฟซ # 8 คุณสามารถมีdefaultและstaticวิธีการได้เช่นกัน
ผู้ใช้มือใหม่

15

อินเทอร์เฟซใช้เมื่อคุณมีสถานการณ์ที่คลาสทั้งหมดมีโครงสร้างเดียวกัน แต่มีฟังก์ชันการทำงานที่แตกต่างกันโดยสิ้นเชิง

คลาสนามธรรมจะใช้เมื่อคุณมีสถานการณ์ว่าคลาสทั้งหมดมีโครงสร้างเหมือนกัน แต่มีฟังก์ชันการทำงานที่เหมือนกันและแตกต่างกัน

ดูบทความ: http://shoaibmk.blogspot.com/2011/09/abstract-class-is-class-which-cannot-be.html


10

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

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

1) Trading system places orders
2) Trading system receives acknowledgements

และสามารถบันทึกได้ในอินเทอร์เฟซ ITradeSystem

public interface ITradeSystem{

     public void placeOrder(IOrder order);
     public void ackOrder(IOrder order);

}

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

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

public class StockTradeSystem implements ITradeSystem{    

    @Override 
    public void placeOrder(IOrder order);
         getMarket().place(order);

    @Override 
    public void ackOrder(IOrder order);
         System.out.println("Order received" + order);    

    private void connectToMarket();
       SocketChannel sock = Socket.open();
       sock.bind(marketAddress); 
       <LOTS MORE MESSY CODE>
    }

    public void findGoodDeals();
       deals = <apply magic wizardry>
       System.out.println("The best stocks to buy are: " + deals);
    }

การใช้งานที่เป็นรูปธรรมจะมีวิธีการที่ยุ่งเหยิงมากมายเช่นconnectToMarket()นี้ แต่findGoodDeals()เทรดเดอร์ทุกคนสนใจจริงๆ

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

public abstract class ABCTradeSystem implements ITradeSystem{    

    public abstract void findGoodDeals();

    @Override 
    public void placeOrder(IOrder order);
         getMarket().place(order);

    @Override 
    public void ackOrder(IOrder order);
         System.out.println("Order received" + order);    

    private void connectToMarket();
       SocketChannel sock = Socket.open();
       sock.bind(marketAddress); 
       <LOTS MORE MESSY CODE>
    }

ระบบการซื้อขายหุ้นของคุณดำเนินการfindGoodDeals()ตามที่คุณได้กำหนดไว้แล้ว

public class StockTradeSystem extends ABCTradeSystem{    

    public void findGoodDeals();
       deals = <apply magic wizardry>
       System.out.println("The best stocks to buy are: " + deals);
    }

แต่ตอนนี้เด็ก FX หวือสามารถสร้างระบบของเธอได้เพียงแค่ให้การใช้งานfindGoodDeals()สำหรับสกุลเงิน เธอไม่จำเป็นต้องใช้การเชื่อมต่อซ็อกเก็ตใหม่หรือแม้แต่วิธีการเชื่อมต่อ!

public class CurrencyTradeSystem extends ABCTradeSystem{    

    public void findGoodDeals();
       ccys = <Genius stuff to find undervalued currencies>
       System.out.println("The best FX spot rates are: " + ccys);
    }

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

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


6

คุณควรใช้คลาสนามธรรมหรืออินเทอร์เฟซใด

พิจารณาใช้คลาสนามธรรมหากข้อความเหล่านี้ใช้กับกรณีการใช้งานของคุณ:

คุณต้องการแบ่งปันรหัสระหว่างชั้นเรียนที่เกี่ยวข้องอย่างใกล้ชิด

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

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

พิจารณาใช้อินเทอร์เฟซหากข้อความเหล่านี้ใช้กับกรณีการใช้งานของคุณ:

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

คุณต้องการระบุลักษณะการทำงานของชนิดข้อมูลหนึ่ง ๆ แต่ไม่ต้องกังวลว่าใครเป็นผู้ดำเนินพฤติกรรมของมัน

คุณต้องการใช้ประโยชน์จากการสืบทอดหลายประเภท

http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html


4

สิ่งต่างๆได้รับการเปลี่ยนแปลงอย่างมากในช่วงสามปีที่ผ่านมาด้วยการเพิ่มความสามารถใหม่ในการเชื่อมต่อกับ Java 8 release

จากหน้าเอกสารของ Oracle บนอินเทอร์เฟซ:

อินเทอร์เฟซเป็นประเภทการอ้างอิงคล้ายกับคลาสที่สามารถมีได้เฉพาะค่าคงที่ลายเซ็นเมธอดเมธอดเริ่มต้นเมธอดแบบคงที่และประเภทที่ซ้อนกัน เมธอดมีอยู่สำหรับเมธอดเริ่มต้นและเมธอดแบบคงที่เท่านั้น

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

อีกหนึ่งข้อพิจารณาที่จะชอบคลาสนามธรรมมากกว่าอินเทอร์เฟซ:

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

ก่อตั้งระดับนามธรรม "คือ" ความสัมพันธ์ระหว่างเรียนที่เกี่ยวข้องและอินเตอร์เฟซให้ "มี" ความสามารถในระหว่างเรียนที่ไม่เกี่ยวข้องกัน


เกี่ยวกับส่วนที่สองของคำถามของคุณซึ่งเป็นที่ถูกต้องให้มากที่สุดของการเขียนโปรแกรมภาษาจาวารวมทั้งก่อนที่จะJava-8ปล่อย

เช่นเคยมีการแลกเปลี่ยนอินเทอร์เฟซให้อิสระกับคุณในเรื่องคลาสพื้นฐานคลาสนามธรรมช่วยให้คุณมีอิสระในการเพิ่มวิธีการใหม่ในภายหลัง - เอริชแกมมา

คุณไม่สามารถเปลี่ยนอินเทอร์เฟซได้โดยไม่ต้องเปลี่ยนสิ่งอื่น ๆ มากมายในโค้ดของคุณ

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

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

ในการเลือกหนึ่งในนั้นระหว่างอินเทอร์เฟซและคลาสนามธรรมหน้าเอกสาร Oracle จะอ้างอิงว่า:

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

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

อ้างถึงคำถามที่เกี่ยวข้องเหล่านี้ก่อนรายละเอียดเพิ่มเติม:

อินเทอร์เฟซเทียบกับคลาสนามธรรม (OO ทั่วไป)

ฉันจะอธิบายความแตกต่างระหว่างอินเทอร์เฟซและคลาสบทคัดย่อได้อย่างไร

สรุป: ความสมดุลจะเอียงมากขึ้นต่อการเชื่อมต่อในขณะนี้

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

รูปแบบการออกแบบบางรูปแบบใช้คลาสนามธรรม (บนอินเทอร์เฟซ) นอกเหนือจากรูปแบบวิธีเทมเพลต

รูปแบบการสร้างสรรค์:

Abstract_factory_pattern

รูปแบบโครงสร้าง:

Decorator_pattern

รูปแบบพฤติกรรม:

Mediator_pattern


สิ่งนี้: "คลาสนามธรรมสร้าง" เป็น "ความสัมพันธ์ระหว่างคลาสที่เกี่ยวข้องและอินเทอร์เฟซที่ให้" มี "ความสามารถระหว่างคลาสที่ไม่เกี่ยวข้อง"
Gabriel

3

คุณไม่ถูกต้อง มีหลายสถานการณ์ เป็นไปไม่ได้ที่จะลดเป็นกฎ 8 คำเดียว


1
เว้นแต่คุณจะคลุมเครือเช่น; ใช้อินเทอร์เฟซทุกครั้งที่ทำได้;)
Peter Lawrey

@PeterLawrey ใช่อย่าปล่อยให้อาร์กิวเมนต์แบบวงกลมทำให้คุณช้าลง ;-)
user207421

นี่คือ "stack overflow" หลังจากทั้งหมด ;) ประเด็นของฉันคือถ้าคุณสามารถใช้อินเทอร์เฟซที่ง่ายกว่านั้นให้ทำเช่นนั้น มิฉะนั้นคุณไม่มีทางเลือกอื่นนอกจากใช้คลาสนามธรรม ฉันไม่เห็นว่ามันซับซ้อนมาก
Peter Lawrey

ฉันคิดว่าคุณสามารถให้แนวคิดที่สร้างสรรค์กว่านี้ได้ ชอบพูดคุยเกี่ยวกับสถานการณ์ที่เป็นตัวแทน /
ดัมส์ H

3

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

หากคุณใช้อินเทอร์เฟซคุณต้องใช้วิธีการทั้งหมด แต่สำหรับคลาสนามธรรมจำนวนวิธีที่คุณต้องใช้อาจน้อยกว่านี้

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


อ้างอิงเพิ่มเติมสำหรับฟังก์ชั่นเสมือนบริสุทธิ์จะเพิ่มข้อมูลเชิงลึกเพิ่มเติมเกี่ยวกับConvergence ของบทคัดย่อชั้นและอินเตอร์เฟซ , Pure virtual functions can also be used where the method declarations are being used to define an interface - similar to what the interface keyword in Java explicitly specifies. In such a use, derived classes will supply all implementations. In such a design pattern, the abstract class which serves as an interface will contain only pure virtual functions, but no data members or ordinary methods. ชิ้นส่วน (1/2)
Abhijeet

ส่วนที่ (2/2) ความแตกต่างของคลาสนามธรรมและอินเทอร์เฟซอธิบายโดยบรรทัดสุดท้ายด้านบนno data members or ordinary methods[ในคลาสบทคัดย่อ]
Abhijeet

3

an interface can't contain non abstract methods while an abstract class canในความคิดของฉันแตกต่างขั้นพื้นฐานก็คือว่า ดังนั้นหากคลาสย่อยมีพฤติกรรมร่วมกันพฤติกรรมนี้สามารถนำไปใช้ในคลาสระดับสูงและสืบทอดมาในคลาสย่อยได้

นอกจากนี้ฉันยังอ้างอิงสิ่งต่อไปนี้จากหนังสือ "ซอฟต์แวร์การออกแบบสถาปัตยกรรมซอฟต์แวร์ใน java"

"ในภาษาการเขียนโปรแกรม Java ไม่มีการรองรับการสืบทอดหลายรายการนั่นหมายถึงคลาสสามารถสืบทอดจากคลาสเดียวเท่านั้นดังนั้นการสืบทอดควรใช้เมื่อจำเป็นจริงๆเท่านั้นเมื่อใดก็ตามที่เป็นไปได้ควรประกาศวิธีการที่แสดงถึงพฤติกรรมร่วมใน รูปแบบของอินเทอร์เฟซ Java ที่จะนำไปใช้โดยคลาสของผู้ใช้งานที่แตกต่างกัน แต่อินเทอร์เฟซต้องทนทุกข์ทรมานจากข้อ จำกัด ที่ไม่สามารถจัดเตรียมวิธีการใช้งานได้ซึ่งหมายความว่าผู้ใช้งานอินเทอร์เฟซทุกคนต้องใช้วิธีการทั้งหมดที่ประกาศไว้ในอินเทอร์เฟซอย่างชัดเจนแม้ว่าบางส่วน เมธอดแสดงถึงส่วนที่ไม่เปลี่ยนแปลงของฟังก์ชันและมีการนำไปใช้งานเหมือนกันทุกประการในคลาสของผู้ใช้งานทั้งหมดซึ่งนำไปสู่โค้ดซ้ำซ้อนตัวอย่างต่อไปนี้แสดงให้เห็นถึงวิธีการใช้รูปแบบ Abstract Parent Class ในกรณีดังกล่าวโดยไม่ต้องใช้วิธีการซ้ำซ้อน "


2

คลาสนามธรรมแตกต่างจากอินเทอร์เฟซในสองด้านที่สำคัญ

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

ฉันจะทำให้อินเทอร์เฟซสามารถมีตัวแปรได้ แต่โดยค่าเริ่มต้นจะเป็นขั้นสุดท้าย
Tomasz Mularczyk

1

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


0

Abstract classes should be extended when you want to some common behavior to get extended. คลาสซูเปอร์บทคัดย่อจะมีพฤติกรรมร่วมกันและจะกำหนดวิธีการเชิงนามธรรม / พฤติกรรมเฉพาะที่คลาสย่อยควรนำไปใช้

Interfaces allows you to change the implementation anytime allowing the interface to be intact.


0

นี่คือความเข้าใจของฉันหวังว่านี่จะช่วยได้

คลาสนามธรรม:

  1. สามารถมีตัวแปรสมาชิกที่สืบทอด (ไม่สามารถทำได้ในอินเทอร์เฟซ)
  2. สามารถมีคอนสตรัคเตอร์ (อินเทอร์เฟซไม่ได้)
  3. วิธีการของมันสามารถมีการมองเห็นใด ๆ (เช่นส่วนตัวป้องกัน ฯลฯ - ในขณะที่วิธีการเชื่อมต่อทั้งหมดเป็นแบบสาธารณะ)
  4. สามารถกำหนดวิธีการ (วิธีการที่มีการใช้งาน)

อินเทอร์เฟซ:

  1. สามารถมีตัวแปรได้ แต่ทั้งหมดเป็นตัวแปรสุดท้ายแบบคงที่สาธารณะ
    • ค่าคงที่ที่ไม่เคยเปลี่ยนแปลงด้วยขอบเขตคงที่
    • ตัวแปรที่ไม่คงที่ต้องการอินสแตนซ์และคุณไม่สามารถสร้างอินสแตนซ์อินเทอร์เฟซได้
  2. วิธีการทั้งหมดเป็นนามธรรม (ไม่มีรหัสในวิธีนามธรรม)
    • โค้ดทั้งหมดจะต้องเขียนในคลาสที่ใช้อินเทอร์เฟซเฉพาะ

0

การใช้บทคัดย่อและส่วนต่อประสาน:

หนึ่งมี "Is-A-Relationship" และอีกคนหนึ่งมี "Has-A-Relationship"

คุณสมบัติเริ่มต้นถูกตั้งค่าเป็นนามธรรมและคุณสมบัติพิเศษสามารถแสดงผ่านอินเทอร์เฟซ

ตัวอย่าง: -> ในมนุษย์เรามีคุณสมบัติเริ่มต้นบางอย่างคือการกินการนอน ฯลฯ แต่ถ้าใครมีกิจกรรมในหลักสูตรอื่น ๆ เช่นว่ายน้ำการเล่น ฯลฯ สิ่งเหล่านี้อาจแสดงโดย Interface

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