"A tree structure of simple and composite objects"
The Composite composes objects into tree
structures and lets clients
treat individual objects and compositions uniformly. Although the
example is abstract, arithmetic expressions are Composites. An
arithmetic expression consists of an operand, an operator (+ - * /),
and another operand. The operand can be a number, or another
arithmetic expresssion. Thus, 2 + 3 and (2 + 3) + (4 * 6) are both
valid expressions.
Rules of thumb
- Composite and Decorator have similar structure diagrams, reflecting the fact that both rely on recursive composition to organize an open-ended number of objects.
- Composite can be traversed with Iterator. Visitor can apply an operation over a Composite. Composite could use Chain of Responsibility to let components access global properties through their parent. It could also use Decorator to override these properties on parts of the composition. It could use Observer to tie one object structure to another and State to let a component change its behavior as its state changes.
- Composite can let you compose a Mediator out of smaller pieces through recursive composition.
- Decorator is designed to let you add responsibilities to objects without subclassing. Composite's focus is not on embellishment but on representation. These intents are distinct but complementary. Consequently, Composite and Decorator are often used in concert.
- Flyweight is often combined with Composite to implement shared leaf nodes.
Giám đốc điều hành của công ty GianDataPool, một công ty mà bạn mới
chuyển đến với vị trí tư vấn, vừa đi khẽ vào phòng làm việc của bạn
và nói lầm bầm gì đó.
“Gì vậy?” bạn hỏi.
Vị giám đốc nhìn quanh với vẻ mặt bí mật, và nói “Tôi có một dự án
tuyệt mật dành cho bạn”
“Tuyệt mật?” bạn nói “Nó nói về cái gì?”
“Đừng to tiếng!” vị giám đốc nói khẽ. “Chúng ta cần một người khách
quan cho chuyện này, Vì vậy tôi mới gặp anh. Chúng ta dường như đang
gặp phải một số vấn đề với việc quản trị và chúng ta cần phải theo
dõi các phó giám đốc – Không ai được biết việc này. Bây giờ, có thể
có hai hay vài vị phó giám đốc làm việc như một lập trình viên vậy”
“Thừa thầy thiếu thợ”, bạn thở dài “Chuyện dài tập của các công ty”
“Chúng ta bắt đầu với khu vực bán hàng,” vị giám đốc nói khẽ “Anh có
thể viết một chương trình duyệt qua hết hồ sơ và in chúng ra chứ?”
“Còn hơn thế nữa”, bạn nói. ”Tôi sẽ sử dụng mẫu Iterator”
Chương này nói về hai mẫu có quan hệ mật thiết với nhau: mẫu Iterator và mẫu Composite. Mẫu Iterator cung cấp cho bạn
cách thức truy cập một bộ phận bên trong một đối tượng mà không cần
phải hiểu rõ cấu trúc nội tại của đối tượng đó. Ví dụ, hãng Sun đã
giới thiệu một kiểu tập hợp trong việc biểu diễn các mối quan hệ
trong ngôn ngữ Java, những tập hợp này cho phép bạn tạo iterator –
một đối tượng đặc biệt được thiết kế cho phép bạn truy cập một phần
tử của tập hợp – để cung cấp một cách thức truy cập dễ dàng.
Mẫu Composite cũng nói về tập hợp. Với mẫu Composite, ý tưởng là bạn
có thể một cấu trúc hình cây nơi mà từng đối tượng sẽ thuộc về một
cái cây -là một nút lá không có nút con, hoặc là một nhánh cây với
nhiều nút lá con – để có thể xử lý trong cùng một cách. Mẫu Composite được thiết kế cho phép bạn xử lý
nhiều đối tượng khác chủng loại trong cùng một tập hợp theo cùng một
cách, và một đối tượng lặp iterator lại vô tình phù hợp tại đây –
dùng để xử lý từng phần tử của một nhánh cây – ví dụ, bạn có
thể duyệt qua hết cây. Chúng ta sẽ thảo luận về hai mẫu trong chương
này.
Truy cập đối tượng với mẫu Iterator
Khi bạn làm việc với một tập hợp nhiều đối tượng, mẫu Iterator là
một giải pháp tốt. Hàng ngày, bạn phải làm việc với nhiều loại tập
hợp như cấu trúc cây, cây nhị phân, mảng, vòng đệm, bảng băm, danh
sách mảng và vân vân… Cách thức mà tập hợp này lưu trữ đối tượng của
nó rất khác nhau, và nếu bạn muốn truy cập dữ liệu của những đối
tượng này, bạn phải học những kỹ thuật khác nhau cho từng loại tập
hợp.
Và đó là nơi mẫu Iterator xuất hiện. Bạn có thể sử dụng một giao
diện interface được xác định rõ ràng để truy cập tới từng phần tử
của tập hợp. Trong những năm qua, các phương pháp cơ bản đã dần trở
nên thích hợp hơn, và chúng cũng xuất hiện xuyên suốt chương này. Sử
dụng những phương pháp này, bạn có thể truy xuất tới các phần tử
trong tập hợp theo cách cơ bản nhất.
Ghi nhớ: Theo sách của Gang of Four (Gof), bạn có thể sử dụng mẫu thiết kế Iterator để “Cung cấp một cách
thức truy cập tuần tự tới các phần tử của một đối tượng tổng hợp, mà
không cần phải tạo dựng riêng các phương pháp truy cập cho đối tượng
tổng hợp này”
Nói cách khác, một Iterator được thiết kế cho phép bạn xử lý nhiều
loại tập hợp khác nhau bằng cách truy cập những phần tử của tập hợp
với cùng một phương pháp, cùng một cách thức định sẵn, mà không cần
phải hiểu rõ về những chi tiết bên trong của những tập hợp này.
Gợi ý: Mẫu thiết kế Iterator đặc biệt quan trọng khi tập hợp bạn
đang xây dựng được tạo thành từ những tập hợp con riêng rẽ, ví dụ
khi bạn chỉnh sửa bảng băm với danh sách mảng, chẳng hạn.
Truy cập đối tượng của bạn với một Iterator
Bạn bắt đầu làm việc với rắc rối giám đốc, đó là phải theo dõi các
phó giám đốc. Trong trường hợp này, bạn quyết định lưu các phó giám
đốc vào trong một tập hợp, với một tập hợp các chức năng cho phép
truy xuất các vị này. Trong phiên bản đầu tiên này, các chức năng cơ
bản mà một Iterator phải có như sau:
was
first
next
isDone
curretnItem
next
hasNext
remove
Hàm next trả về phần tử kế tiếp trong tập hợp, hàm hasNext trả về
giá
trị True nếu vẫn còn phần tử trong tập hợp và trả về false trong
trường
hợp ngược lại, hàm remove cho phép bạn gỡ bỏ một phần tử trong tập
hợp.
Đó là cách Iterator làm việc – Nó cung cấp một giao diện đơn giản,
nhất quán để làm việc với các tập hợp khác nhau. Giả sử rằng khách
hàng
phải làm việc với một tập hợp phức tạp và rắc rối ( như hình sau) và
không biết cách thức làm việc với nó như thế nào.
Khách hàng có thể sử dụng iterator để làm cầu nối với tập hợp, và khách hàng có thể sử dụng các phương thức cơ bản của Iterator để giao tiếp với tập hợp. Như hình sau:
Ghi nhớ: Sách của GoF nói rằng, bạn sử dụng mẫu Composites để
“Tạo ra các đối tượng trong một cấu trúc hình cây để biểu diễn cho
một
cấu trúc phân cấp. Mẫu Composites cho phép khách hàng xử lý một đối
tượng riêng hoặc toàn bộ đối tượng theo cùng một cách”
Đó là những gì bạn cần – một mẫu thiết kế cho phép bạn xử lý các nút
lá hoặc các nhánh của cấu trúc cây theo cách giống nhau bởi vì bạn
muốn
có thể in ra thông tất cả các phó giám đốc riêng lẻ, trong một khu
vực,
hoặc cả công ty, chỉ bằng cách gọi hàm print.
Mẫu thiết kế Composites rất phù hợp với mẫu Iterator bởi vì khi bạn
gọi từng khu vực để in chính nó, nó có thể dễ dàng duyệt qua từng
phó
giám đốc một. Đó là đặc điểm điển hình của mẫu Composite – khi bạn yêu
cầu một nhánh thực hiện một hành động gì đó , nó sẽ lặp qua tất cả
các
lá con và nhánh con của nó.
Ý tưởng đằng sau của mẫu Composite là việc xử lý các nút lá và nhánh
trong một cấu trúc hình cây sẽ giống nhau. Điều này giúp cho việc xử
lý
các cấu trúc phức tạp theo dạng hình cây sẽ dễ dàng hơn bởi vì bạn
không
cần phải thiết lập các hàm khác nhau cho từng phần của cấu trúc.
Để thực hiện mẫu Composite, sách của GoF khuyên rằng bạn nên sử một
lớp trừu tượng như là một lớp cơ sở cho cả nút lá và các nhánh trong
cấu
trúc cây. Việc làm này giúp cho các nút lá và các nhánh sẽ có chung
một
tập hợp các hàm, đó là tất cả những gì mẫu Composite muốn nói tới.
Source code treeview
Result:
Ref:
https://haihth.wordpress.com/2013/02/23/dp-chapter8/
https://sourcemaking.com/design_patterns/composite