Kẻ thế vai hoàn hảo!

Chắc hẳn chúng ta ai cũng đang sử dụng mạng đúng không, và đôi khi chúng ta cần phải cấu hình máy chủ proxy, đặc biệt là khi ở công ty, chúng ta sẽ cần phải cấu hình máy chủ proxy để chặn các trang #web độc hại hoặc không được phép truy cập, đó chính là một trong những ví dụ điển hình của Proxy design pattern

Mục tiêu của Proxy

Proxy pattern ra đời với mục tiêu:

  1. Che dấu sự phức tạp của lớp cài đặt
  2. Mở rộng để thêm vào một số thao tác mà không làm ảnh hưởng đến lớp cài đặt cũ và cũng không không làm ảnh hưởng đến các lớp đang sử dụng lớp cũ

Ví dụ

Mục tiêu thứ 2 hơi khó hiểu đúng không mọi người, vậy chúng ta hãy lấy ví dụ về máy chủ proxy nhé. Giả sử chúng ta đang phải code một máy chủ chuyên kiểm soát việc truy cập #network cho một công ty, hạ tầng của họ đã có sẵn các lớp thế này

interface NetworkClient {
    String call(String url);
}
class FreeNetworkClient implements NetworkClient {
    @Override
    public String call(String url) {
        return "It's response from " + url;
    }
}

Nhiệm vụ của chúng ta là phải thêm tính năng chặn các trang web không được phép truy cập. Thách thức đặt ra là chúng ta không được phép sửa code mà đang chạy ổn định rồi. Như vậy bắt buộc chúng ta cần tạo ra một lớp thừa kế lớp cũ và không còn cách nào khác, và lớp thừa kế này chính là Proxy.

class NetworkClientProxy implements NetworkClient {
    private final Set<String> blackListURLs = new HashSet<>();
    private final NetworkClient realClient = new FreeNetworkClient();

    public NetworkClientProxy addBlackURL(String blackURL) {
        this.blackListURLs.add(blackURL);
        return this;
    }

    public String call(String url) {
        if(blackListURLs.contains(url))
            throw new IllegalArgumentException(url + " is in black list");
        return realClient.call(url);
    }
}

Khi sử dụng sẽ thế này:

NetworkClient freeClient = new FreeNetworkClient();
NetworkClient proxy = new NetworkClientProxy(freeClient)
        .addBlackURL("blackurl.com");
System.out.println(proxy.call("youngmokeys.org"));
try {
    proxy.call("blackurl.com");
}
catch (Exception e) {
    System.out.println("error: " + e.getMessage());
}

Chúng ta có thể thấy là các lớp cũ vẫn được giữ nguyên, và chúng ta vẫn tiếp tục sử dụng NetworkClient mà không có bất kì thay đổi gì

Kết luận

Nếu bạn đang đau đầu với việc nâng cấp hệ thống cũ và bổ sung các tính năng mới, Proxy pattern có thể là một lựa chọn đơn giản nhưng vô cùng hiệu quả, giúp chúng ta tránh được việc thay đổi các lớp đang chạy ổn định và đảm bảo được nguyên tắc OpenClose trong thiết kế hệ thống phần mềm.