+1

Dependency Injection Trong Go

I. Định Nghĩa

Dependency Injection là kỹ thuật giúp giảm sự phụ thuộc giữa các module code bằng cách "tiêm" các dependencies (các đối tượng hoặc dữ liệu mà một đối tượng cần để thực hiện công việc của nó) thay vì để đối tượng tự tạo ra chúng. Trong ngôn ngữ Go, điều này thường được thực hiện thông qua interfaces. Một đối tượng chỉ cần định nghĩa những gì nó cần (thông qua một interface) và các đối tượng khác có thể cung cấp những gì nó cần nếu chúng tuân thủ interface đó.

II. Ví dụ

Trong ví dụ này chúng ta sẽ tạo ra một dịch vụ gửi tin nhắn qua Email và SMS.

Đầu tiên, chúng ta định nghĩa một interface MessageService với một phương thức SendMessage. Interface này không cung cấp chi tiết về việc làm thế nào để gửi tin nhắn, chỉ đơn giản là yêu cầu một "dịch vụ tin nhắn" phải có khả năng gửi tin nhắn.

    // MessageService handles some message
    type MessageService interface {
        SendMessage(message string, receiver string) error
    }

Tiếp theo, chúng ta định nghĩa hai struct SMSServiceEmailService, cả hai đều implement MessageService interface. Điều này có nghĩa là cả hai đều cung cấp phương thức SendMessage, nhưng cách thực hiện của mỗi dịch vụ có thể khác nhau.

   
   // SMSService is a implementation of MessageService
    type SMSService struct{}

    func (s *SMSService) SendMessage(message string, receiver string) error {
        fmt.Printf("Send SMS: %s to %s\n", message, receiver)
        return nil
    }

    // EmailService is another implementation of MessageService
    type EmailService struct{}

    func (e *EmailService) SendMessage(message string, receiver string) error {
        fmt.Printf("Send Email: %s to %s\n", message, receiver)
        return nil
    }

Tiếp theo tạo MyApplication struct có một trường messageService kiểu MessageService.

// MyApplication uses a service to send messages
type MyApplication struct {
    messageService MessageService
}

func (a *MyApplication) processMessages(message string, receiver string) error {
    err := a.messageService.SendMessage(message, receiver)
    if err != nil {
        return err
    }
    return nil
}

Điều này có nghĩa là MyApplication không cần biết chi tiết về việc làm thế nào để gửi tin nhắn, chỉ cần biết rằng nó có một dịch vụ có thể gửi tin nhắn. Đây chính là Dependency Injection (DI): MyApplication không tạo ra một MessageService, thay vào đó, nó được cung cấp một MessageService khi được tạo.

Trong hàm main, chúng ta tạo ra một SMSServiceEmailService, và "tiêm" chúng vào MyApplication thông qua trường messageService.

func main() {
    smsService := &SMSService{}
    app := &MyApplication{messageService: smsService}
    app.processMessages("Hello World", "123")

    emailService := &EmailService{}
    app.messageService = emailService
    app.processMessages("Hello World", "abc@example.com")
}   

Trong ví dụ trên, MyApplication không cần biết rằng nó đang sử dụng SMSService hay EmailService để gửi tin nhắn. Nó chỉ cần biết rằng nó có một dịch vụ để gửi tin nhắn. Điều này giúp giảm sự phụ thuộc giữa các module và giúp chúng ta dễ dàng thay đổi hoặc thử nghiệm với các dịch vụ khác nhau.


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.