หากคลาสพึ่งพาแหล่งข้อมูลภายในอย่างน้อยหนึ่งแหล่ง และแหล่งข้อมูลเหล่านั้นส่งผลต่อการทำงานของคลาส ไม่ควรใช้ Singleton และ Static Utility Class
คลาสไม่ควรสร้างแหล่งข้อมูลเหล่านี้เอง แต่ควรส่งผ่านแหล่งข้อมูลที่จำเป็นไปยัง Constructor แทน การฉีด Dependency (Dependency Injection) จะช่วยปรับปรุงความยืดหยุ่น การนำกลับมาใช้ใหม่ และความสะดวกในการทดสอบของคลาส
ตัวอย่าง
ตัวอย่างการใช้ Static Utility Class
Utility Class นี้สมมติว่าใช้พจนานุกรมเพียงหนึ่งเดียว แต่ในความเป็นจริง พจนานุกรมอาจแบ่งตามภาษา และอาจมีพจนานุกรมเฉพาะสำหรับคำศัพท์เฉพาะอีกด้วย
ตัวอย่างการใช้ Singleton Class
Singleton Class ก็มีข้อเสียเช่นเดียวกัน เนื่องจากสมมติว่าใช้พจนานุกรมเพียงหนึ่งเดียว
วิธีแก้ปัญหาที่ 1 - ลบ final keyword ออกจาก field
เราสามารถลบ final keyword ออกจาก dictionary ใน Static Utility Class หรือ Singleton Class และออกแบบให้เปลี่ยน dictionary เป็นพจนานุกรมอื่นจากภายนอกได้ แต่แนวทางนี้ใช้ยาก และอาจทำให้เกิดปัญหาเรื่องความพร้อมกัน (Concurrency Issue) ในสภาพแวดล้อมแบบ Multi-thread
วิธีแก้ปัญหาที่ 2 - ใช้ Dependency Injection
จากตัวอย่างนี้ เราสามารถเรียนรู้ได้ว่า Static Class และ Singleton Class ไม่ควรพึ่งพาแหล่งข้อมูลภายใน นั่นหมายความว่าควรส่งผ่านแหล่งข้อมูลจากภายนอกเข้ามาแทน
คลาสที่ใช้ Dependency Injection จะสามารถรับประกันความคงที่ (Immutability) ได้ด้วย final keyword และยังรองรับ Instance ของแหล่งข้อมูลหลายๆ อันอีกด้วย นอกจากนี้ Dependency Injection สามารถนำไปใช้ได้ทั้งใน Constructor Static Factory และ Builder
Dependency Injection ไม่เพียงแต่ส่งผ่านแหล่งข้อมูลโดยตรงเท่านั้น แต่ยังสามารถส่งผ่าน Factory ของแหล่งข้อมูลได้ด้วย Factory คือ Object ที่สร้าง Instance ของ Type เฉพาะซ้ำๆ ทุกครั้งที่ถูกเรียกใช้ รูปแบบนี้เรียกว่า Factory Method Pattern และ Supplier<T> ใน Java 8 เป็นตัวอย่างที่สมบูรณ์แบบของ Factory
โดยทั่วไปจะใช้ Type Parameter ที่มี Bounded Wildcard เพื่อจำกัด Type ของ Factory วิธีนี้ช่วยให้ Client สามารถส่งผ่าน Factory ใดๆ ก็ได้ตราบใดที่เป็น Subtype ของ Type ที่ระบุ
Dependency Injection ช่วยเพิ่มความยืดหยุ่นและความสะดวกในการทดสอบ แต่ในโครงการที่มี Dependency จำนวนมากอาจส่งผลให้เกิดค่าใช้จ่ายสูง ในกรณีเช่นนี้ เราสามารถใช้ Dependency Injection Framework (เช่น Dagger, Guice, Spring) เพื่อลดค่าใช้จ่ายได้
ความคิดเห็น0