Flyweight Pattern La Gi?
Flyweight Pattern La Gi?

Học Design Pattern: Flyweight Pattern – Khi Của Ít Nhưng Lòng Nhiều

Flyweight Pattern là cách diễn đạt Flexing khi mấy anh em dev không muốn dùng từ Cache – Caching – Memorization.

Câu Chuyện Flyweight Pattern: Tài Nguyên Có Hạn, Nhưng Bạn Cần Dùng Nhiều

Hãy ngược dòng thời gian về thuở sơ khai, khi RAM và Ổ Cứng là hàng hiếm, các nhà phát triển Game thời ấy đã đối mặt với những thách thức Khó – Nam Cường như thế nào!

Trong Game chỉ cần vẽ một nhân vật thôi ta phải qua 1 loạt công đoạn: load Texture từ ổ cứng, cắt tỉa (map Rect) texture, rồi sau đó mới Draw lên màn hình. Thử tưởng tượng trong những game như Mario, Contra hay Car Racer, có cả trăm nhân vật đồng thời xuất hiện, mỗi ông một Texture riêng thì máy thời đó chịu nổi không?

RAM phân mảnh, game giật tung chảo là cái chắc!

Vậy là các OG của Game Dev đã nghĩ ra độc chiêu: dồn hết Texture của nhân vật vào một tấm Texture khổng lồ, load 1 lần duy nhất, rồi dùng metadata để cắt đúng miếng của từng nhân vật ra để vẽ.

Nghe quen không? Đó chính là Flyweight Pattern nguyên thuỷ đó! Tuy chưa được đặt tên, nhưng cái tư duy SHARE tài nguyên để tối ưu hiệu suất này đã đi trước thời đại cả chục năm, giúp game chạy phà phà trên những con máy cổ và mở đường cho những sáng tạo đồ hoạ đỉnh cao sau này.

Áp Dụng Flyweight Pattern Cho Hiện Tại

Ở thời đại công nghệ ngày nay, Flyweight Pattern không hề lỗi thời, mà ngược lại, nó cực kỳ quan trọng trong các ứng dụng quy mô lớn. Tại sao ư? Vì caching là chìa khóa để tăng tốc ứng dụng và mang lại trải nghiệm người dùng mượt mà.

Anh em cứ ngẫm mà xem, những công nghệ như Redis hay CDN, về bản chất, đều là hiện thân của nguyên lý Flyweight. Chúng chia sẻ và tái sử dụng dữ liệu, giúp tối ưu hiệu năng.

Gần gũi hơn, trong phát triển ứng dụng di động, việc quản lý hiển thị một lượng lớn Bitmap là một bài toán hóc búa. Làm thế nào để đảm bảo Bitmap được hiển thị chính xác, đầy đủ và nhanh chóng? Câu trả lời là phải dùng caching thật rát nhất có thể thôi. Và Caching, đó chính là Flyweight Pattern đó anh em!

interface BitmapCache {
  fun putCache(key: String, bmp: Bitmap): Boolean
  fun retrieveCache(key: String): Bitmap?
  fun invalidate(): Unit
}

Một Vài Vấn Đề Lưu Ý Với Flyweight Pattern

Khi áp dụng Flyweight Pattern, đặc biệt là trong các kịch bản caching, việc phân tích kỹ lưỡng các yêu cầu của bài toán là vô cùng quan trọng. Chúng ta cần xác định chính xác loại dữ liệu nào sẽ được cache, từ đó tối ưu hóa chiến lược lưu trữ và truy xuất. Tần suất đọc và ghi dữ liệu cũng là một yếu tố then chốt, ảnh hưởng đến quyết định về thời gian tồn tại của cache và các cơ chế đồng bộ.

Việc xác định rõ ràng thời điểm và cách thức invalidate cache là bắt buộc để đảm bảo tính chính xác của thông tin. Cuối cùng, để tránh tình trạng nghẽn cổ chai và cải thiện hiệu suất, hãy luôn ưu tiên xử lý bất đồng bộ trong Flyweight Pattern.

Riêng chuyên đề về Cache mình sẽ viết thêm nhiều bài nữa trên blog @dantech. Trong bài này mong anh em hiểu và nắm được core concept của Flyweight Pattern là ok rồi.

Chúc anh em thành công!