Golang Design Patterns – Prototype. Khởi tạo đối tượng một cách nhanh chóng

Tram Ho

Mẫu pattern cuối cùng thuộc Creational Pattern trong series Design Patterns mà mình muốn giới thiệu. Cũng xoay quanh việc khởi tạo đối tượng, nhưng không phức tạp như các mẫu thiết kế cùng loại, ta tận dụng lại những đối tượng đã có sẵn để phục vụ cho việc khởi tạo. Chi tiết về mẫu thiết kế này mình sẽ nói sau đây.

I. Prototype – Creational Patterns

Mục tiêu của Prototype hướng tới những đối tượng đã được khởi tạo trước đó (như tại thời điểm compile) và cho phép chúng ta clone đối tượng đó không giới hạn số lần vào thời điểm runtime chẳng hạn. Lấy ví dụ khi build một trang web gồm 3 thành phần header-body-footer, sẽ có rất nhiều trang chỉ cần thay đổi nội dung ở phần body, và phần header và footer là như nhau. Khi đó prototype sẽ giúp chúng ta tiết kiệm chi phí và thời gian cho việc khởi tạo lại header và footer.

II. Prototype mang lại cho developers những gì?

Tránh lặp đi lặp lại việc khởi tạo không đáng có, đó là những gì mà mẫu thiết kế này mang lại. Thử tưởng tượng header của trang chứa rất nhiều thông tin lấy từ API, việc chuyển trang đồng nghĩa phải đi fetch lại toàn bộ thông tin thì quả là dư thừa không đáng có. Một cách tóm tắt, Prototype hướng đến:

  • Những đối tượng thường được tái sử dụng có chi phí khởi tạo cao và (có thể), cung cấp default value cho chúng
  • Giảm tiêu tốn tài nguyên cho việc khởi tạo phức tạp (CPU, resources…)

III. Ví dụ thực tế

Chúng ta lấy luôn ví dụ ở trên để triển khai nhé. Bài toán đặt ra là 1 trang web bao gồm 3 routes:

  • /login (không header và footer)
  • /home (có header và footer)
  • /profile (có header và footer)
    Dễ nhận thấy ở đây có 2 dạng layout Blank Và Main (mình hay đặt tên vậy 😂). Blank thì đơn thuần là một layout chỉ chứa content (body). Main là một layout chứa 3 phần header – body (dynamic) – footer.

Mẫu Prototype áp dụng vào trường hợp này cần tuân thủ những quy tắc sau:

  • Có 2 layouts (Blank và Main), layout luôn yêu cầu tham số truyền vào là body (content của trang)
  • Khi yêu cầu chuyển trang trong cùng 1 layout (home -> profile), đối tượng trang mới được tạo ra nhưng header và footer là những instance được tận dụng lại
  • Một Page Info sẽ bao gồm các thông tin của page là route, header, body, footer (mặc định là nil)

IV. Implementation

Khởi tạo struct Layout như sau, layout bao gồm 3 thành phần (header, body, footer). Một Layout bao gồm các methods SetBody, GetInfo và 2 layouts được phép clone là BlankMain

  • Blank Layout bao gồm các thành phần từ Layout và một instance mặc định (header và footer nil)

  • Với Main Layout thì phức tạp hơn, để khởi tạo header của Main Layout phải trả qua một vài công đoạn như fetch data từ API, xử lý logic…và việc khởi tạo mất tầm 1s:

  • Sau cùng là định nghĩa struct cho Page, bao gồm route, layout và các method NewPage và GetInfo. Ở đây NewPage nhận vào tham số là route và pageLayout, ở đây mình đưa công việc clone layout vào:

  • Bây giờ mình sẽ run đoạn code theo yêu cầu bài toán, bao gồm 3 route: /home, /profile/login. Đảm bảo layout instance không bị ảnh hưởng trong quá trình clone:

  • Kết quả:

image.png

V. Lời kết

Prototype design pattern được xem như một công cụ hỗ trợ mạnh mẽ cho việc khởi tạo nhanh những đối tượng mà tiết kiệm được rất nhiều thời gian và tài nguyên, cũng có thể xem prototype như một build caches. Có thể thấy được sự trùng lặp trong cách triển khai giữa các mẫu creational design patterns, nhưng vẫn có những sự khác biệt nhỏ khiến các pattern này thể hiện sức mạnh nếu được sử dụng đúng cách.

Mình cũng giới thiệu qua toàn bộ 5 mẫu thiết kế thuộc nhóm khởi tạo thường được developers sử dụng nhất. Hi vọng gặp các bạn ở các chapers khác

Cảm ơn các bạn đã xem bài viết

VI. References

Go Design Patterns (Mario Castro Contreras)

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo