5. Nhóm các mẫu cấu trúc tĩnh (Structural Patterns)
5.4 Composite Pattern
a. Mục đích, ý nghĩa
Các ứng dụng đồ họa như bộsoạn thảo hình vẽ và các hệ thống lưu giữ biểu đồ cho phép người sử dụng xây dựng lên các lược đồ phức tạp khác xa với các thành phần cơ bản, đơn giản. Người sử dụng có thể nhóm một số các thành phần để tạo thành các thành phần khác lớn hơn, và các thành phần lớn hơn này lại có thể được nhóm lại để tạo thành các thành phần lớn hơn nữa. Một cài đặt đơn giản có thể xác định các lớp cho các thành phần đồ họa cơ bản như Text và Line, cộng với các lớp khác cho phép hoạt động như các khuôn chứa các thành phần cơ bản đó. Nhưng có một vấn đề với cách tiếp cận này, đó là, mã sử dụng các lớp đó phải tác động lên các đối tượng nguyên thủy (cơ bản) và các đối tượng bao hàmcác thành phần nguyên thủy ấy là khác nhau ngay cả khi hầu hết thời gian người sử dụng tác động lên chúng là như nhau. Có sự phân biệt các đối tượng này làm cho ứng dụng trở nên phức tạp hơn. Composite pattern đề cập đến việc sử dụng các thành phần đệ quy để làm cho các client không tạo ra sự phân biệt trên. Giải pháp của mẫu Composite là một lớp trừu tượng biểu diễn cả các thành phần cơ bản và các lớp chứa chúng. Lớp này cũng xác định các thao tác truy nhập và quản lý
các con của nó.
Component (DrawingElement)
- Khai báo giao diện cho các đối tượng trong một khối kết tập.
- Cài đặt các phương thức mặc định cho giao diện chung của các lớp một cách phù hợp.
- Khai báo một giao diện cho việc truy cập và quản lý các thành phần con của nó - Định nghĩa một giao diện cho việc truy cập các đối tượng cha của các thành phần theomột cấu trúc đệ quy và cài đặt nó một cách phù hợp nhất.
Leaf (PrimitiveElement)
- Đại diện cho một đối tượng nút làtrong khối kết tập. Một lá là một nút không có con. - Định nghĩa hành vi cho các đối tượng nguyên thuỷ trong khối kết tập Composite (CompositeElement)
- Định nghĩa hành vi cho các thành phần mà có con. - Lưu trữ các thành phần con
- Cài đặt toán tử quan hệ giữa các con trong giao diên của thành phần Client (CompositeApp)
- Vận dụng các đối tượng trong khối kết tập thông qua giao diện của thành phần
c. Ví dụ
// The Interface
{
void Add(IComponent<T> c); IComponent<T> Remove(T s); string Display(int depth); IComponent<T> Find(T s); T Name { get; set; }
}
// The Component
public class Component<T> : IComponent<T> {
public T Name { get; set; } public Component(T name) {
Name = name; }
public void Add(IComponent<T> c) {
Console.WriteLine("Cannot add to an item"); }
public IComponent<T> Remove(T s) {
Console.WriteLine("Cannot remove directly"); return this;
}
public string Display(int depth) {
return new String('-', depth) + Name + "\n"; }
{ if (s.Equals(Name)) return this; else return null; } } // The Composite
public class Composite<T> : IComponent<T> {
List<IComponent<T>> list; public T Name { get; set; } public Composite(T name) {
Name = name;
list = new List<IComponent<T>>(); }
public void Add(IComponent<T> c) {
list.Add(c); }
IComponent<T> holder = null;
// Finds the item from a particular point in the structure // and returns the composite from which it was removed // If not found, return the point as given
public IComponent<T> Remove(T s) {
holder = this;
if (holder != null) {
(holder as Composite<T>).list.Remove(p); return holder;
} else
return this; }
// Recursively looks for an item public IComponent<T> Find(T s) {
holder = this;
if (Name.Equals(s)) return this; IComponent<T> found = null; foreach (IComponent<T> c in list) { found = c.Find(s); if (found != null) break; } return found; }
// Displays items in a format indicating their level in the composite structure public string Display(int depth)
{
StringBuilder s = new StringBuilder(new String('-', depth)); s.Append("Set " + Name + " length :" + list.Count + "\n"); foreach (IComponent<T> component in list)
s.Append(component.Display(depth + 2)); } return s.ToString(); } } 5.5 Adapter Pattern a. Mục đích, ý nghĩa
Trong lập trình máy tính, dạng thức thiết kế adapter hay còn gọi là dạng thức thiết kế
điều hợp điều chỉnh một interface của một lớp vào một interface khác mà người dùng
mong đợi. Một adapter cho phép các lớp làm việc với nhau, mà bình thường là không thể do sự không tương thích về interfaces, bằng cách bao đóng interface của riêng nó cho phù hợp với một lớp có sẵn.
Có 2 loại mẫu điều hợp (adapter pattern):
• Loại Object Adapter pattern - Trong loại mẫu adapter pattern này
thì adapter chứa một thể hiện của lớp mà nó bao đóng. Trong tình huống này thì adapter sẽ thực hiện việc gọi hàm đến đối tượng thể hiện được bao đóng đó để thực hiện tác vụ cần thiết.
Mẫu Object Adapter biểu diễn bằng UML. Đối tượng adapter che giấu interface của adaptee khỏi client.
• Loại Class Adapter pattern - Loại adapter này dùng đa kế thừa để đạt được mục
đích này. Đối tượng adapter này được tạo ra bằng cách kế thừa các interfaces từ cả interface mong đợi và interface đã có sẵn. Đối tượng của mẫu Adapter rất hay được
dùng ở các ngôn ngữ phổ biến, như Java, không được hỗ trợ đa kế thừa thực vì các nhà thiết kế các ngôn ngữ này cho rằng chúng là những thói quen không tốt.
Mẫu Class Adapter biểu diễn bằng UML.
Mẫu adapter rất hữu ích trong những tình huống khi tồn tại sẵn một lớp cung cấp một số hay toàn bộ dịch vụ mà bạn cần nhưng không có interface mà bạn cần. Một ví dụ tốt trong cuộc sống thực là một adapter chuyển interface của một Document Object Model từ một tài liệu XML thành một cấu trúc cây mà có thể hiển thị. Một liên kết đến một hướng dẫn sử dụng mẫu thiết kế được liệt kê ở bên dưới.