1. Proxy Pattern là gì

Mẫu proxy là một mẫu thiết kế cấu trúc hoạt động như một proxy để kiểm soát quyền truy cập vào một đối tượng cụ thể. Dựa trên đối tượng mục tiêu (đối tượng đang được proxy), mẫu proxy cung cấp một đối tượng proxy thông qua đó các client có thể truy cập vào đối tượng mục tiêu, cho phép thêm chức năng bổ sung vào đối tượng mục tiêu.

1.1 Định nghĩa của Mẫu Proxy

Mẫu proxy là một mẫu thiết kế mà liên quan đến sự cộng tác của hai hoặc nhiều đối tượng. Một đối tượng là đối tượng mục tiêu thực sự được gọi, trong khi một hoặc nhiều đối tượng khác hoạt động như đối tượng proxy. Các đối tượng proxy chặn quyền truy cập vào đối tượng mục tiêu, cung cấp một cách gián tiếp để truy cập vào đối tượng mục tiêu.

1.2 Mục đích và Đối tượng của Mẫu Proxy

Mục đích chính của mẫu proxy là cung cấp một cách gián tiếp để truy cập vào đối tượng mục tiêu, cho phép thêm chức năng bổ sung vào đối tượng mục tiêu. Đối tượng proxy có thể xử lý các logic chung, như kiểm soát quyền truy cập vào đối tượng mục tiêu, caching và logging. Mẫu proxy cũng có thể thực hiện tải chậm, khởi tạo đối tượng mục tiêu chỉ khi cần thiết.

2. Đặc điểm và Ưu điểm của Mẫu Proxy

Mẫu proxy có những đặc điểm và ưu điểm sau:

  • Có thể mở rộng chức năng của đối tượng mục tiêu mà không cần sửa đổi đối tượng đó.
  • Có thể kiểm soát quyền truy cập vào đối tượng mục tiêu thông qua đối tượng proxy.
  • Có thể thực hiện các hoạt động bổ sung trước hoặc sau khi truy cập vào đối tượng mục tiêu.
  • Có thể thực hiện tải chậm, khởi tạo đối tượng mục tiêu chỉ khi cần thiết.

3. Các Ví dụ Ứng dụng Thực tế của Mẫu Proxy

Mẫu proxy được sử dụng rộng rãi trong nhiều kịch bản ứng dụng. Dưới đây là một số ví dụ thông thường về việc áp dụng thực tế:

  • Máy Ủy Quyền Từ Xa: Sử dụng để truy cập đối tượng trên mạng cục bộ.
  • Ủy Quyền Ảo: Sử dụng để tạo đối tượng đắt tiền theo nhu cầu.
  • Máy Ủy Quyền Bảo Mật: Sử dụng để kiểm soát quyền truy cập vào đối tượng.
  • Tham Chiếu Thông Minh: Sử dụng để thực hiện các hoạt động bổ sung khi truy cập vào đối tượng, như đếm đối tượng.

4.1 Sơ đồ Lớp UML

Dưới đây là sơ đồ lớp UML của Mẫu Proxy trong Golang:

Mẫu Proxy Golang

4.2 Giới thiệu Ví dụ

Giả sử chúng ta có một giao diện Subject định nghĩa phương thức Request. Chúng ta có một lớp cụ thể RealSubject, thực hiện giao diện Subject. Sau đó, chúng ta tạo một lớp proxy Proxy, chứa một đối tượng RealSubject và cũng thực hiện giao diện Subject. Trong phương thức Request của lớp Proxy, chúng ta có thể thực hiện các hoạt động bổ sung trước hoặc sau khi gọi phương thức Request của RealSubject.

4.3 Bước 1: Định nghĩa Giao diện Proxy

Trước hết, chúng ta cần định nghĩa một giao diện Subject chứa phương thức Request:

package main

type Subject interface {
    Request()
}

4.4 Bước 2: Thực hiện Đối tượng Mục tiêu

Tiếp theo, chúng ta thực hiện đối tượng mục tiêu cụ thể RealSubject, thực hiện giao diện Subject:

package main

import "fmt"

type RealSubject struct {}

func (r *RealSubject) Request() {
    fmt.Println("RealSubject: Xử lý Yêu cầu")
}

4.5 Bước 3: Thực hiện Đối tượng Proxy

Tiếp theo, chúng ta tạo một đối tượng proxy, Proxy, chứa một đối tượng RealSubject và thực hiện giao diện Subject. Trong phương thức Request của Proxy, chúng ta có thể thực hiện một số hoạt động bổ sung trước hoặc sau khi gọi phương thức Request của RealSubject:

package main

import "fmt"

type Proxy struct {
    realSubject *RealSubject
}

func (p *Proxy) Request() {
    fmt.Println("Proxy: Trước Yêu cầu")
    
    if p.realSubject == nil {
        p.realSubject = &RealSubject{}
    }
    
    p.realSubject.Request()
    
    fmt.Println("Proxy: Sau Yêu cầu")
}

4.6 Bước 4: Gọi Đối tượng Proxy

Cuối cùng, chúng ta có thể sử dụng đối tượng proxy, Proxy, để gọi các phương thức của đối tượng đang được proxy, RealSubject:

package main

func main() {
    proxy := Proxy{}
    proxy.Request()
}

Chạy mã trên sẽ tạo ra kết quả sau:

Proxy: Trước Yêu cầu
RealSubject: Xử lý Yêu cầu
Proxy: Sau Yêu cầu

5.1 Sự khác biệt và Mối liên kết giữa Mẫu Proxy và Mẫu Decorator

Cả mẫu proxy và mẫu decorator đều là mẫu thiết kế cấu trúc, đều chứa một đối tượng mục tiêu và một đối tượng proxy/decorator. Tuy nhiên, có một số khác biệt giữa hai mẫu này:

  • Mẫu proxy thường liên quan đến việc kiểm soát truy cập vào đối tượng mục tiêu, trong khi mẫu decorator tập trung nhiều hơn vào việc mở rộng đối tượng mục tiêu.
  • Mẫu proxy thường thực hiện các hoạt động bổ sung trước hoặc sau đối tượng mục tiêu, trong khi mẫu decorator động thêm chức năng phụ vào đối tượng mục tiêu.

5.2 So sánh giữa Proxy Tĩnh và Proxy Động

Mẫu proxy có thể được chia thành proxy tĩnh và proxy động. Proxy tĩnh xác định loại đối tượng proxy tại thời điểm biên dịch, và đối tượng proxy được viết thủ công bởi các lập trình viên. Ngược lại, proxy động tạo đối tượng proxy động vào thời điểm chạy dựa trên giao diện của đối tượng mục tiêu. Proxy động linh hoạt hơn nhưng cũng phức tạp hơn so với phiên bản tĩnh.

5.3 Ứng dụng của Mẫu Proxy trong Kiến trúc Microservices

Mẫu proxy có thể được áp dụng trong kiến trúc microservices. Ví dụ, chúng ta có thể sử dụng một proxy để bao bọc việc truy cập vào các microservices khác và triển khai cơ chế như cân bằng tải, giới hạn tốc độ và cắt mạch ở tầng proxy. Điều này có thể nâng cao tính đáng tin cậy và hiệu suất của hệ thống. Mẫu proxy cũng có thể được sử dụng để triển khai chức năng phát hiện dịch vụ và định tuyến.