มีคำตอบที่ดีมากมายที่นี่ แต่ฉันมักพบว่าการใช้อินเทอร์เฟซทั้งสองและคลาสนามธรรมเป็นเส้นทางที่ดีที่สุด ลองพิจารณาตัวอย่างที่สร้างขึ้นนี้:
คุณเป็นนักพัฒนาซอฟต์แวร์ที่ธนาคารเพื่อการลงทุนและจำเป็นต้องสร้างระบบที่ส่งคำสั่งซื้อเข้าสู่ตลาด อินเตอร์เฟซของคุณจับความคิดทั่วไปมากที่สุดของสิ่งที่ระบบการซื้อขายไม่ ,
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()
ไม่เป็นส่วนหนึ่งของอินเทอร์เฟซ อย่าลืมว่าอินเทอร์เฟซกำหนดองค์ประกอบทั่วไปส่วนใหญ่ของระบบการซื้อขาย วิศวกรคนอื่นอาจพัฒนาระบบการซื้อขายที่แตกต่างกันโดยสิ้นเชิงโดยที่พวกเขาไม่สนใจที่จะหาข้อเสนอที่ดี อินเทอร์เฟซรับประกันได้ว่าฝ่ายขายสามารถเชื่อมต่อกับระบบของตนได้เช่นกันดังนั้นจึงไม่ควรให้อินเทอร์เฟซของคุณยุ่งเกี่ยวกับแนวคิดการใช้งานเช่น