Dependency Injection (DI)

Bài toán kinh điển “bóng đèn - đui đèn”: thiết kế tốt cho phép thay đổi linh hoạt giữa bóng và đui; thiết kế tồi (tight coupling) khiến không thể thay thế - phải mua cả cái đèn mới thay vì chỉ thay bóng.

Không dùng DI (tight coupling)

class Lamp {
    public function __construct()
    {
        // Class bóng đèn GẮN CHẶT vào class Đèn qua từ khóa new
        $this->bulb = new Bulb();
    }
 
    public function turnOn() { /* ... */ }
}

Dùng DI

class Lamp
{
    // Injection thông qua Interface Bulb (hoặc Abstract Class Bulb)
    public function __construct(Bulb $bulb) {
        $this->bulb = $bulb;
    }
 
    public function turnOn() {
        $this->bulb->turnOn();
    }
}
 
$lamp = new Lamp(new GreenBulb()); // đèn màu xanh
$lamp = new Lamp(new RedBulb());   // đèn màu đỏ

Cái đui đã tách khỏi đèn - việc của ta là thiết kế lớp trừu tượng = cái trôn xoáy đèn. Đèn chỉ cần “implement interface đui đèn” là luôn xoáy được vào đui và chắc chắn hoạt động. DI giúp chúng ta tạo nên tính Đa hình - chế ra đủ loại đèn mình muốn.

Cốt lõi

  • DI đại diện cho triết lý Composition over Inheritance: một đối tượng nên được tạo thành từ các viên gạch nhỏ hơn TỪ BÊN NGOÀI, thay vì tự khởi tạo trong chính đối tượng đó.
  • DI giúp test dễ hơn nhiều: muốn test cái đui - có sẵn đèn mẫu (Mocking Object), cắm vào, sáng, pass test. Không có DI thì class rất khó test.
  • Tư duy phân tách code thành đơn vị nhỏ để lắp ghép: nhiều cái đèn làm thành ngọn hải đăng; đèn nào vỡ/hỏng (bug) → dễ cô lập, thay thế, sửa chữa.
  • Với Laravel: DI đi cùng Service Container (binding các lớp trừu tượng) - xem Inversion of Control.

Liên quan