Dependency Injection คือรูปแบบการเขียนโปรแกรม ที่ช่วยให้ Code ของเรามีความยืดหยุ่น และทดสอบได้ง่ายขึ้น โดยลดการยึดติดกันของ Object
แนวคิดพื้นฐาน: “เลิกสร้างเอง แต่รอรับจากภายนอก”
โดยปกติเวลา Class หนึ่งต้องการใช้งานอีก Class หนึ่ง เรามักจะเขียนคำสั่ง new ขึ้นมาในตัว Class นั้นเลย แต่ DI บอกว่า “อย่าสร้างเอง” ให้รอรับ Object นั้นผ่านทาง Constructor หรือ Method แทน
เปรียบเทียบให้เห็นภาพ
- แบบเดิม: คุณอยากกินกาแฟ คุณต้องไปปลูกต้นกาแฟ คั่วเมล็ด และชงเอง
- แบบ DI: คุณแค่บอกว่า “ต้องการกาแฟ” แล้วมีพนักงานยกมาเสิร์ฟให้ คุณมีหน้าที่แค่ดื่ม
ทำไมเราถึงต้องใช้ Dependency Injection ?
- Loose Coupling: Class ต่าง ๆ ไม่ยึดติดกันแน่นจนเกินไป ทำให้การแก้ไข Code ในส่วนหนึ่งไม่กระทบกับส่วนอื่นโดยไม่จำเป็น
- Easier Testing: เราสามารถส่ง “Object จำลอง” เข้าไปแทนที่ Object จริงในขณะทดสอบได้ เช่น แทนที่จะต่อ Database จริง เราก็ส่ง Database จำลองเข้าไปแทน
- Maintainability: เมื่อต้องการเปลี่ยน Implementation เราแค่เปลี่ยนที่จุดฉีด จุดเดียว ไม่ต้องไล่แก้ทุก Class
ประเภทของ Dependency Injection
การฉีด Dependency เข้าไปใน Class หลัก ๆ มี 3 วิธี
- Constructor Injection: ส่ง Dependency ผ่านทาง Constructor
- Setter Injection: ส่ง Dependency ผ่านทาง Setter Method หลังจากสร้าง Object แล้ว
- Interface Injection: ตัว Dependency จะมี Interface กำหนดไว้เพื่อให้ Injector ส่งข้อมูลมาให้
ตัวอย่าง Code
แบบที่ไม่ได้ใช้ DI
แบบนี้ Car จะยึดติดกับ GasEngine เสมอ ถ้าอยากเปลี่ยนเป็น ElectricEngine ต้องรื้อ Code ใหม่
public class Car { private GasEngine engine; public Car () { this.engine = new GasEngine () ; // สร้างเองภายใน ยึดติดแน่น }
}
แบบที่ใช้ DI
แบบนี้ Car รับอะไรก็ได้ที่เป็น IEngine ทำให้เราเปลี่ยนประเภทเครื่องยนต์ได้โดยไม่ต้องแก้ Code ใน Class Car
public class Car { private IEngine _engine; // รับเครื่องยนต์จากภายนอก public Car (IEngine engine) { this._engine = engine; }
}
สรุป
Dependency Injection ไม่ได้เป็นเพียงเทคนิคการเขียนโปรแกรม แต่เป็นหัวใจสำคัญของการออกแบบ Software สมัยใหม่ที่เน้นความยืดหยุ่นและการจัดการระบบขนาดใหญ่ให้มีประสิทธิภาพครับ
อ่านเพิ่มเติม