Nội dung
Composite là một mẫu thiết kế cấu trúc cho phép sắp xếp các đối tượng thành một cấu trúc giống như cây và làm việc với nó như thể nó là một đối tượng đơn lẻ.
Composite đã trở thành một giải pháp khá phổ biến cho hầu hết các vấn đề yêu cầu xây dựng cấu trúc cây. Tính năng tuyệt vời của Composite là khả năng chạy các phương thức đệ quy trên toàn bộ cấu trúc cây và tổng hợp kết quả.
Cách sử dụng mẫu
Cách sử dụng: Mẫu Composite khá phổ biến trong C#. Nó thường được sử dụng để biểu thị thứ bậc của các thành phần giao diện người dùng hoặc chương trình hoạt động với đồ thị.
Nhận dạng: Nếu bạn có cây đối tượng và mỗi đối tượng của cây là một phần của cùng một hệ thống phân cấp lớp, thì đây rất có thể là một composite. Nếu các phương thức của các lớp này ủy thác công việc cho các đối tượng con của cây và thực hiện nó thông qua lớp cơ sở / giao diện của hệ thống phân cấp, thì đây chắc chắn là một composite.
Chương trình mẫu
Program.cs
using System;
using System.Collections.Generic;
namespace DesignPatterns.Composite.Conceptual
{
// Lớp cơ sở Component khai báo các hoạt động chung cho cả các đối tượng
// đơn giản và phức tạp của một composition.
abstract class Component
{
public Component() { }
// Component có thể thực hiện một số hành vi mặc định hoặc để nó
// cho các lớp cụ thể (bằng cách khai báo phương thức trừu tượng).
public abstract string Operation();
// Trong một số trường hợp, sẽ có lợi nếu xác định các hoạt động quản lý lớp
// con ngay trong lớp Component. Bằng cách này, bạn sẽ không cần hiển thị
// bất kỳ lớp component cụ thể nào với client, ngay cả trong quá trình tạo cây
// đối tượng. Nhược điểm là các phương thức này sẽ rỗng đối với các nút leaf.
public virtual void Add(Component component)
{
throw new NotImplementedException();
}
public virtual void Remove(Component component)
{
throw new NotImplementedException();
}
// Có thể cung cấp một phương thức cho phép client xác định liệu một
// component có nút con hay không.
public virtual bool IsComposite()
{
return true;
}
}
// Lớp Lá (Leaf) đại diện cho các đối tượng cuối cùng của một cây.
// Một chiếc lá không thể có con.
//
// Thông thường, các đối tượng Leaf thực hiện công việc thực tế, trong khi các
// đối tượng Composite chỉ ủy quyền cho các thành phần con của chúng.
class Leaf : Component
{
public override string Operation()
{
return "Leaf";
}
public override bool IsComposite()
{
return false;
}
}
// Lớp Composite đại diện cho các thành phần phức tạp có thể có con. Thông
// thường, các đối tượng Composite ủy thác công việc thực tế cho con cái của
// chúng và sau đó "tổng hợp" kết quả.
class Composite : Component
{
protected List<Component> _children = new List<Component>();
public override void Add(Component component)
{
this._children.Add(component);
}
public override void Remove(Component component)
{
this._children.Remove(component);
}
// Composite thực thi logic chính của nó theo một cách cụ thể. Nó duyệt đệ
// quy qua tất cả các con của nó, thu thập và tổng hợp kết quả của chúng.
// Vì các con của composite truyền những lệnh gọi này cho con của chúng
// và cứ thế, kết quả là toàn bộ cây đối tượng được duyệt qua.
public override string Operation()
{
int i = 0;
string result = "Branch(";
foreach (Component component in this._children)
{
result += component.Operation();
if (i != this._children.Count - 1)
{
result += "+";
}
i++;
}
return result + ")";
}
}
class Client
{
// Client hoạt động với tất cả các component thông qua giao diện cơ sở.
public void ClientCode(Component leaf)
{
Console.WriteLine($"RESULT: {leaf.Operation()}\n");
}
// Nhờ các hoạt động quản lý lớp con được khai báo trong lớp Component cơ sở,
// client có thể hoạt động với bất kỳ thành phần nào, đơn giản hay phức tạp mà
// không phụ thuộc vào các lớp cụ thể của chúng.
public void ClientCode2(Component component1, Component component2)
{
if (component1.IsComposite())
{
component1.Add(component2);
}
Console.WriteLine($"RESULT: {component1.Operation()}");
}
}
class Program
{
static void Main(string[] args)
{
Client client = new Client();
// Bằng cách này, client có thể hỗ trợ các thành phần lá đơn giản...
Leaf leaf = new Leaf();
Console.WriteLine("Client: I get a simple component:");
client.ClientCode(leaf);
// ...cũng như các thành phần phức tạp.
Composite tree = new Composite();
Composite branch1 = new Composite();
branch1.Add(new Leaf());
branch1.Add(new Leaf());
Composite branch2 = new Composite();
branch2.Add(new Leaf());
tree.Add(branch1);
tree.Add(branch2);
Console.WriteLine("Client: Now I've got a composite tree:");
client.ClientCode(tree);
Console.Write("Client: I don't need to check the components classes even when managing the tree:\n");
client.ClientCode2(tree, leaf);
}
}
}
Kết quả
Client: I've got a simple component:
RESULT: Leaf
Client: Now I've got a composite tree:
RESULT: Branch(Branch(Leaf+Leaf)+Branch(Leaf))
Client: I don't need to check the components classes even when managing the tree:
RESULT: Branch(Branch(Leaf+Leaf)+Branch(Leaf)+Leaf)
Để lại một bình luận