Design Pattern - Proxy
Bài đăng này đã không được cập nhật trong 3 năm
Proxy là gì?
Proxy dịch ra thì nó có nghĩa là "ủy quyền" hay "đại diện".
Mục đích xây dựng Proxy pattern
cũng chính vì muốn tạo ra một đối tượng sẽ ủy quyền, thay thế cho một đối tượng khác.
Chúng ta xem ví dụ đơn giản sau:
Ta xây dựng một class BankAccount
đơn giản để theo dõi các hoạt động của bank account
class BankAccount
attr_reader :balance
def initialize(starting_balance=0)
@balance = starting_balance
end
def deposit(amount)
@balance += amount
end
def withdraw(amount)
@balance -= amount
end
end
Đồng thời, ta xây dựng 1 class proxy cho BankAccount
class BankAccountProxy
def initialize(real_object)
@real_object = real_object
end
def balance
@real_object.balance
end
def deposit(amount)
@real_object.deposit(amount)
end
def withdraw(amount)
@real_object.withdraw(amount)
end
end
Ta thấy rằng class BankAccountProxy
có các phương thức thực hiện giống hệt như BankAccount, thậm chí nó còn sử dụng chính đối tượng của BankAccount
.
Như vậy về bản chất BankAccountProxy
hoàn toàn có thể thay thế BankAccount
với các thao tác và vai trò tương đương nhưng nó lại không phải BankAccount
. Có thể nói BankAccountProxy
đóng vai trò là ủy quyền của BankAccount
.
Vì sao phải dùng Proxy?
Một câu hỏi đặt ra là vì sao chúng ta không khởi tạo và gọi trực tiếp class BankAccount
mà phải thông qua Proxy.
Thực ra không phải bất cứ class hay object nào cũng cần phải có Proxy, chỉ có những class hoặc object đặc biệt mà chúng ta phải ủy quyền khi:
- Muốn bảo vệ quyền truy xuất vào các phương thức của object.
- Muốn bổ sung trước khi thực hiện phương thức của object.
- Muốn tạo object với chức năng được nâng cao hơn theo yêu cầu.
Làm thế nào để xây dựng 1 Proxy pattern
Proxy pattern về cơ bản sẽ gồm 3 thành phần chính:
- 1 class interface giao tiếp với client
- 1 class service sẽ thực hiện các thao tác thực sự
- 1 class proxy sẽ thực hiện các bước kiểm tra và gọi tới đối tượng của class service thật để thực hiện các thao tác sau khi kiểm tra.
Proxy bảo vệ các phương thức như thế nào
Cách đơn giản nhất là chúng ta thêm vào một method kiểm tra mỗi khi gọi tới các method ủy quyền.
Ví dụ như khi truy xuất các phương thức của BankAccount, chúng ta phải kiểm tra xem user đã đăng nhập chưa.
require 'etc'
class AccountProtectionProxy
def initialize(real_account, owner_name)
@subject = real_account
@owner_name = owner_name
end
def deposit(amount)
check_access
return @subject.deposit(amount)
end
def withdraw(amount)
check_access
return @subject.withdraw(amount)
end
def balance
check_access
return @subject.balance
end
def check_access
if Etc.getlogin != @owner_name
raise "Illegal access: #{Etc.getlogin} cannot access account."
end
end
end
Rõ ràng, chúng ta có thể đưa các mã kiểm tra vào chính class BankAccount
nhưng việc đưa mã kiểm tra vào Proxy giúp ta có cái nhìn tập trung hơn.
Proxy chỉ quan tâm xem ai được phép thực thi mà không cần hiểu thực thi như thế nào. Điều này giúp ta dễ dàng kiểm soát được vấn đề an ninh và bảo mật hoặc có thể dễ dàng thay đổi các phương thức trong BankAccount mà không còn lo ngại về vấn đề bảo mật nữa, giúp ta đóng gói được các thông tin cần được bảo vệ.
Tham khảo
Github (updating):https://github.com/ducnhat1989/design-patterns-in-ruby
Sách: “DESIGN PATTERNS IN RUBY” của tác giả Russ Olsen
Bài viết liên quan:
All rights reserved