Proxy: truy cập từ xa và virtual ảnh bìa

Định nghĩa Proxy, người đại diện cho tài nguyên ở xa qua mạng, và ảnh bìa đĩa than tải chậm với virtual proxy.
KhóDesign pattern ~60 phút

Giới thiệu

Bài này học người đại diện đứng giữa khách và hàng thật. Dùng để gọi máy xa và tải ảnh nặng không chờ.

Kiến thức cần nhớ

Định nghĩa Proxy

  • Định nghĩa: đại diện cho object khác để kiểm soát truy cập.
  • Đại diện và hàng thật tuân cùng một giao diện.
  • Ví dụ đời thường: như lễ tân nhận yêu cầu thay giám đốc.
  • Khách không biết mình đang nói với đại diện.
  • Từ khóa là đại diện và kiểm soát truy cập.

Remote proxy

  • Định nghĩa: đại diện địa phương cho máy ở xa qua mạng.
  • Ông chủ gọi đại diện như gọi máy thật tại chỗ.
  • Ví dụ đời thường: như gọi shipper thay vì tới quán xa.
  • Đại diện lo đóng gói yêu cầu gửi qua mạng.
  • Bên kia mở gói rồi hỏi máy thật.
Loại proxyNỗi đauCách giải
RemoteMáy ở xa, gọi khóĐại diện tại chỗ
VirtualẢnh nặng, tải chậmHiện tạm rồi tải sau
Bảo vệCần kiểm quyềnChặn trước khi vào

Virtual proxy

  • Định nghĩa: giữ chỗ trước, tải hàng nặng sau.
  • Danh sách hiện ngay, ảnh bìa tải dần từng cái.
  • Ví dụ đời thường: như khung xám chờ ảnh tải xong.
  • Tải hết trước khi hiện thì người dùng chờ dài.
  • Click món nào mới tải nặng món đó.

Ví dụ

  • Input: hỏi tồn kho máy kẹo ở xa -> Output: gọi đại diện tại văn phòng.
  • Giải thích: đại diện chuyển lời qua mạng tới máy thật.
# Đại diện kiểm soát trước khi gọi hàng thật
class Proxy:
    def lay_kho(self):
        if not self.quyen:  # kiểm tra trước
            return "từ chối"
        return self.may_that.lay_kho()  # chuyển lời

💻 Bài tập

Ngôn ngữ: C++17 (hoặc Java). Dùng GumballMachine và GumballMonitor ngày 86. Nộp vào day-098/.

Bài 1: Remote proxy qua socket

struct GumballMachineRemote {
  virtual int count() = 0; virtual std::string location() = 0; virtual std::string state() = 0;
  virtual ~GumballMachineRemote() = default;
};
Thành phầnViệc phải làm
GumballServerChạy GumballMachine thật, nghe TCP cổng 5000. Nhận dòng COUNT, LOCATION, STATE, trả 1 dòng kết quả
GumballStub : GumballMachineRemoteMở socket, gửi lệnh, đọc kết quả. Lỗi mạng ném RemoteException
GumballMonitorChỉ biết GumballMachineRemote&, không biết là máy thật hay stub
Monitor(máy thật) và Monitor(stub tới server) in cùng báo cáo
Tắt server rồi gọi stub -> RemoteException, monitor in "không liên lạc được"

Chạy 3 server ở 3 cổng (3 máy ở 3 thành phố). Monitor in báo cáo cả 3.

Bài 2: Virtual proxy cho ảnh bìa

struct Icon { virtual int width() = 0; virtual int height() = 0; virtual std::string paint() = 0; virtual ~Icon() = default; };
class ImageIcon : public Icon { /* constructor tải ảnh: giả lập sleep 2 giây */ };
class ImageProxy : public Icon {
  // chưa tải xong: width/height trả 800x600, paint trả "Đang tải ảnh bìa..."
  // lần gọi paint đầu tiên: khởi động tải ở luồng nền
  // tải xong: ủy thác mọi lời gọi cho ImageIcon
};
Tạo 20 ImageProxy -> tức thì (dưới 10 ms)
paint() ngay lập tức -> "Đang tải ảnh bìa..."
paint() sau 3 giây   -> nội dung ảnh thật
Chỉ ảnh nào được paint mới tải (đếm số lần tải)

Bài 3: Caching proxy (nâng cao)

WeatherService::forecast(city) giả lập gọi API mất 500 ms.

  1. Viết CachingWeatherProxy cùng interface: cache kết quả 10 phút theo city (dùng đồng hồ giả để test).
  2. Viết LoggingWeatherProxy ghi thời gian mỗi lần gọi. Chồng 2 proxy lên nhau.
  3. Viết 3 câu: Proxy khác Decorator ở điểm nào khi cả hai đều bọc cùng interface.

✅ Tiêu chí hoàn thành

  • Monitor chạy với cả máy thật và stub, xử lý lỗi mạng.
  • Virtual proxy chỉ tải ảnh khi cần, không chặn luồng chính.
  • Caching proxy test bằng đồng hồ giả.
  • Phân biệt được Proxy, Decorator, Adapter bằng mục đích.

❓ Câu hỏi ôn tập

  • Proxy khác hàng thật ở đâu?
  • Remote proxy giấu cái gì?
  • Virtual proxy tải khi nào?
  • Từ khóa của Proxy là gì?

🌕 Bạn đã hoàn thành ngày 98. Làm hết bài tập phía trên rồi sang ngày tiếp theo.

Bớt paste mù, hiểu sâu từng dòng mình viết.

180 Days Challenge. 180 ngày cai nghiện vibe code.