Một trong những khía cạnh quan trọng nhất trong quá trình phát triển một ứng dụng mà các lập trình viên phải đối đầu là sự thay đổi. Khi muốn thêm hoặc loại bỏ một tính năng của một đối tượng, điều đầu tiên chúng ta nghĩ đến là thừa kế (extends). Tuy nhiên, thừa kế không khả thi vì nó là static, chúng ta không thể thêm các lớp con mới vào một chương trình khi nó đã được biên dịch và thực thi. Để giải quyết vấn đề này, chúng ta có thể sử dụng Decorator Pattern được giới thiệu trong phần tiếp theo của bài viết này.
Decorator pattern là một trong những Pattern thuộc nhóm cấu trúc (Structural Pattern). Nó cho phép người dùng thêm chức năng mới vào đối tượng hiện tại mà không muốn ảnh hưởng đến các đối tượng khác. Kiểu thiết kế này có cấu trúc hoạt động như một lớp bao bọc (wrap) cho lớp hiện có. Mỗi khi cần thêm tính năng mới, đối tượng hiện có được wrap trong một đối tượng mới (decorator class).
Decorator pattern sử dụng composition thay vì inheritance (thừa kế) để mở rộng đối tượng. Decorator pattern còn được gọi là Wrapper hay Smart Proxy.
Decorator pattern hoạt động dựa trên một đối tượng đặc biệt, được gọi là decorator (hay wrapper). Nó có cùng một interface như một đối tượng mà nó cần bao bọc (wrap), vì vậy phía client sẽ không nhận thấy khi bạn đưa cho nó một wrapper thay vì đối tượng gốc.
Tất cả các wrapper có một trường để lưu trữ một giá trị của một đối tượng gốc. Hầu hết các wrapper khởi tạo trường đó với một đối tượng được truyền vào constructor của chúng.
Vậy làm thế nào để có thể thay đổi hành vi của đối tượng? Như đã đề cập, wrapper có cùng interface với các đối tượng đích. Khi bạn gọi một phương thức decorator, nó thực hiện cùng một phương thức trong một đối tượng được wrap và sau đó thêm một cái gì đó (tính năng mới) vào kết quả, công việc này tùy thuộc vào logic nghiệp vụ.
Các thành phần trong mẫu thiết kế Decorator:
Ví dụ:
Để đơn giản hơn, chúng ta xem ví dụ về một hệ thống quản lý dự án, nơi nhân viên đang làm việc với các vai trò khác nhau, chẳng hạn như thành viên nhóm (team member), trưởng nhóm (team lead) và người quản lý (manager). Một thành viên trong nhóm chịu trách nhiệm thực hiện các nhiệm vụ được giao và phối hợp với các thành viên khác để hoàn thành nhiệm vụ nhóm. Mặt khác, một trưởng nhóm phải quản lý và cộng tác với các thành viên trong nhóm của mình và lập kế hoạch nhiệm vụ của họ. Tương tự như vậy, một người quản lý có thêm một số trách nhiệm đối với một trưởng nhóm như quản lý yêu cầu dự án, tiến độ, phân công công việc.
Sau đây là các thành phần tham gia vào hệ thống và hành vi của chúng:
Với cách làm thông thường, chúng ta có sơ đồ như sau:
Bất cứ khi nào một thành viên trong nhóm trở thành một Team Lead, chúng ta phải tạo một đối tượng mới của Team Lead và đối tượng trước đó tham chiếu vào nhân viên đó (Team Member trong nhóm) có thể bị hủy hoặc lưu trữ. Đó không phải là cách tiếp cận được khuyến nghị khi nhân viên vẫn là một phần của tổ chức của bạn. Tương tự như trường hợp với Manager, khi một nhân viên trở thành người quản lý từ một Team Lead / Team Member.
Một trường hợp khác là khi một nhân viên có thể thực hiện trách nhiệm của một Team Member trong nhóm cũng như trách nhiệm của Team Lead hoặc một Manager. Trong trường hợp đó, bạn cần tạo hai đối tượng cho cùng một nhân viên là hoàn toàn sai.
Trong các kịch bản này, một Team Member/ Team Lead có thể có thêm trách nhiệm trong lúc thực hiện (run-time). Và trách nhiệm của họ có thể được chỉ định / thu hồi trong lúc run-time.
Hãy xem sơ đồ bên dưới để thấy được cách chúng ta áp dụng Decorator Pattern như thế nào trong trường hợp này.
Như bạn thấy, với Decorator hệ thống của chúng ta linh hoạt hơn rất nhiều. Chúng ta có thể dễ dàng gán một nhân viên sang vai trò TeamMember, TeamLeader, Manager.
Giống nhau:
Khác nhau:
You need to login in order to like this post: click here
YOU MIGHT ALSO LIKE