Hiểu về Dependency Injection

Bài viết được sự cho phép của tác giả Nguyễn Hữu Khanh

Search trên Google các bạn có thể tìm thấy hàng đống bài viết về cái chủ đề này, mỗi người một kiểu trình bày khác nhau. Có thể có bạn sẽ lĩnh hội rất nhanh, cũng có thể không nên mình xin tổng hợp lại và cố gắng viết lại nó theo một kiểu dễ hiểu nhất (sẽ cố gắng hết sức 😀 ).

Ý tưởng chính của Dependency Injection đó là bạn không phụ thuộc vào ai cả và người khác cũng không phụ thuộc vào bạn. Khi cần mình sẽ gọi bạn và bạn cũng vậy.

Để mình nói cụ thể hơn nhé!

  SQL Injection là gì? Cách giảm thiểu và phòng ngừa SQL Injection
  Codepen là gì ? Hướng dẫn sử dụng Codepen cơ bản

Ngày xưa mình thường viết code như thế này:

Giả sử bạn có một đối tượng là Circle, đối tượng này có một phương thức là draw() như sau:

public class Circle {
public void draw() {
System.out.println("Drawing circle ...");
}
}

Giờ mình muốn sử dụng đối tượng này để vẽ hình tròn, mình sẽ khởi tạo đối tượng Circle ngay trong constructor và mình sẽ code như sau:

public class Drawing {
public Circle circle;

public Drawing() {
circle = new Cirle();
}

public void preparing() {
System.out.println("Preparing ...");
}

public void draw() {
circle.draw();
}

public static void main(String[] args) {
Drawing drawing = new Drawing();
drawing.draw();
}
}

Rõ ràng bạn thấy đối tượng Drawing của mình đang phụ thuộc vào đối tượng Circle của bạn (nghĩa là mình đang phụ thuộc vào bạn đấy), bởi vì mỗi khi chạy ứng dụng, đối tượng Drawing lại phải giữ luôn thông tin của đối tượng Circle. Đây là nhược điểm thứ nhất của cách code này.

Nhược điểm thứ hai đó là nếu sau này mình muốn vẽ một tam giác, mình lại phải đi khai báo lại đối tượng khác để đáp ứng nhu cầu của mình. Đối tượng Drawing của mình vì thế cứ phải thay đổi liên tục theo nhu cầu.

Vậy giờ làm sao để giải quyết hai nhược điểm này?

Nhược điểm thứ hai chúng ta có thể giải quyết dễ dàng bằng cách sử dụng interface. Đối tượng Circle của bạn giờ sẽ hiện thực một interface tên là Shape, cụ thể như sau:

public interface Shape {
public void draw();
}

Sau này mình muốn vẽ tam giác thì chỉ cần viết thêm một lớp mới và hiện thực interface Shape là được.

Đối với nhược điểm thứ nhất, Dependency Injection sinh ra để giải quyết nó.

Hãy xem Dependency Injection giải quyết như thế nào nhé, mình xin sửa lại đối tượng Drawing như sau:

public class Drawing {
private Shape shape;

public Drawing(Shape shape) {
this.shape = shape;
}

public void setShape(Shape shape) {
this.shape = shape;
}

public void preparing() {
System.out.println("Preparing ...");
}

public void draw() {
shape.draw();
}
}

Các bạn thấy đó, nếu bây giờ mình chỉ muốn đối tượng Drawing của mình chỉ chuẩn bị các dụng cụ để vẽ mà thôi, mình sẽ không cần gọi đến đối tượng Circle của bạn, code sẽ như sau:

Drawing drawing = new Drawing(null);
drawing.preparing();

Và giờ sau khi chuẩn bị xong, mình sẽ cần bạn để vẽ một hình tròn, mình sẽ gọi đến bạn:

Drawing drawing = new Drawing(null);
drawing.preparing();

Shape shape = new Circle();
drawing.setShape(shape);
drawing.draw();

Thật ra, những code này nhiều bạn đã làm rồi nhưng không biết nó là Dependency Injection thôi.

Bài viết gốc được đăng tải tại huongdanjava.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev