![]() |
![]() |
Separation of Concerns with Interfaces |
![]() |
|
| By PradubKeng |
|
เกริ่นนำ
หลังจากที่เราได้คุยกันถึงภาษาจาว่าและเทคโนโลยีที่เกี่ยวข้องมาพอสมควร วันนี้เรามาเปลี่ยนบรรยากาศคุยกันในเรื่องพื้น ๆ ที่เป็นหัวใจสำคัญอย่างหนึ่งของการออกแบบระบบในภาษาจาว่ากันบ้าง หลายคนในช่วงเวลาว่าง อาจจะเคยลองนั่งอ่านซ๊อดโค๊ดของโปรแกรมพวก open source ใหญ่ ๆ เช่น Apache Tomcat, Xalan หรือ JBoss
ส่ิงหนึ่งที่มักจะพบเห็นได้ชัดจากโปรแกรมเหล่านี้คือมีการใช้คอนเซ็ปของ Interface มาช่วยในการออกแบบค่อนข้างมาก โดยบางทีจะเห็นว่า
Interface เพียงหนึ่งตัว จะมีคลาสมากมายมารุมทำการ implement ตัว Interface ตัวนั้น
วิธีการเช่นนี้มีจุุดประสงค์และข้อดีอย่างไรในเชิงของการออกแบบ วันนี้เรามาคุยกันซักเล็กน้อยกับเรื่องนี้
Separation of Concerns
สมมุติว่าเรามีโทรศัพท์มือถืออยู่เครื่องหนึ่ง สิ่งที่เราต้องเรียนรู้เพื่อใช้ในการโทรศัพท์ออกจากโทรศัพท์มือถือของเรามีเพียงสามอย่างคือ
ถ้าไม่พูดถึงความสวยงามหรือฟังก์ชันอื่น ๆ ของโทรศัพท์ ไม่ว่าโทรศัพท์มือถือเครื่องไหน
ถ้ามีสามฟังก์ชันนี้ เราก็สามารถใช้โทรติดต่อสื่อสารได้เหมือนกัน โทรศัพท์มือถือของเราถ้าเปรียบเทียบกับ
* วิธีการเขียน Interface ในเชิง programming จะไม่ถูกกล่าวถึงในบทความนี้
ผู้ที่สนใจสามารถศึกษารายละเอียดเพิ่มเติมได้จาก Resources
เราทำการ define ตัว
คลาส User มีเพียงหนึ่งฟังก์ชันคือ makeACall(...) ซึ่งรับ MobilePhone Interface
เป็น argument ข้อสังเกตอย่างหนึ่งสำหรับฟังก์ชันนี้คือ ฟังก์ชันนี้จะไม่สนใจว่าคลาสที่ใส่เข้ามาเป็นตัว
argument จะเป็นคลาสอะไร แต่คลาสที่จะใส่เข้ามานั้นจะต้องทำการ implement ตัว MobilePhone Interface
แม้ว่าเราจะทำการ define ตัวโทรศัพท์มือถือเอาไว้ให้คนใช้แล้ว แต่จริง ๆ ตอนนี้เรามีเพียงตัว
คลาส NokiaPhone ถือว่าเป็นคลาสชนิด MobilePhone เพราะได้ทำการ implement
ตัว MobilePhone Interface ด้วยการใส่ส่วนที่เป็น implementation เข้าไปยังฟังก์ชัน
insert(), connect() และ end() ทีนี้เรามาดูคลาสที่ใช้แทนโทรศัพท์มือถือยี่ห้อ SamSung กันบ้าง
คลาส SamSung ก็ถือว่าเป็นคลาสชนิด MobilePhone อีกเช่นกันเพราะตัวมันได้ทำการ
implement ฟังก์ชันทั้งหมดที่ถูก define อยู่ใน MobilePhone Interface เหมือนกับที่คลาส
NokiaPhone ทำเพียงแต่เราจะสังเกตเห็นว่าโค๊ดที่อยู่ในฟังก์ชันต่าง ๆ ของคลาส SamSung
จะไม่เหมือนกับโค๊ดที่อยู่ในคลาส NokiaPhone ซึ่งพูดง่าย ๆ ก็คือคลาสทั้งสองเป็นคลาสชนิด MobilePhone
แต่มีส่วนที่เป็น implementation ที่แตกต่างกัน ส่วนที่แตกต่างกันนี้ผู้ใช้จะมองไม่เห็นและไม่จำเป็นจะต้องให้ความสนใจกับมัน
ผู้ใช้สามารถเรียกใช้โทรศัพท์ทั้งสองยี่ห้อผ่านทางฟังก์ชันต่าง ๆ ที่เหมือนกันซึ่งถูกบรรจุอยู่ใน MobilePhone Interface
อย่างไรก็ตามผลที่ได้จะแตกต่างกันดังตัวอย่างข้างล่าง
ถ้าลองรัน ผลที่ได้ก็จะออกมาเป็นดังนี้... User user = new User(); // both NokiaPhone and SamSungPhone are "MobilePhone" MobilePhone nokiaPhone = new NokiaPhone(); MobilePhone samsungPhone = new SamSungPhone(); user.makeACall(nokiaPhone); user.makeACall(samsungPhone); ... (MobilePhoneTest.java)
เราจะสังเกตเห็นว่าในคลาส>javac MobilePhoneTest.java >java MobilePhoneTest Nokia - Insert number: Tod Tod Tod ~~~ Nokia - Connect and Talk: %^&$#@$# Nokia - End conversation: Oh Yeh!!! SamSung - Insert number: Wee Wee Wee ~~~ SamSung - Connect and Talk: zZZzZz SamSung - End conversation: Cheer Cheer!!! User ข้างต้นจะไม่มีการเกี่ยวข้องกับคลาส NokiaPhone
หรือ SamSungPhone เลย สิ่งที่คลาส User รับรู้จะมีเพียง MobilePhone Interface
เท่านั้น ในการเขียนส่วนที่เป็น Implementation ให้กับ MobilePhone Interface ตัวคลาส
NokiaPhone และคลาส SamSungPhone ก็ไม่มีการเกี่ยวข้องกับคลาส User อีกเช่นกัน
คลาส User และคลาสที่เป็นส่วน Implementation ของ MobilePhone Interface (NokiaPhone
และ SamSungPhone) เหล่านี้เกี่ยวข้องกันโดยอาศัย MobilePhone Interface เป็นตัวเชื่อม
โดยแต่ละคนจะให้ความสนใจใน Interface นี้ในแง่มุมที่แตกต่างกัน (คลาส User
สนใจเพียงการใช้โทรศัทพ์มือถือ คลาส NokiaPhone และ SamSungPhone สนใจเพียงการสร้างโทรศัพท์เท่านั้น)
ตัวอย่างของโทรศัพท์มือถือข้างต้นถูกนำมาใช้ในโลกของจาว่าในลักษณะของ Resources
|