Шаблон Компоновщик позволяет упростить и стандартизировать взаимодействие между клиентом и группой объектов, представляющих древовидную структуру. Этот шаблон используется, если необходимо, чтобы клиент одинаково обращался как с составным объектом, так и с отдельными его частями.
Рассмотрим элементы шаблона Компоновщик (рис. 4). Интерфейс IComponent является общим для составных объектов и их частей. С точки зрения клиента все объекты являются экземплярами IComponent – клиент не различает составные объекты и их части. Класс Leaf представляет «неделимые» объекты (название взято по аналогии с наименованием элемента древовидной структуры). Класс Composite описывает составной объект, он может содержать как неделимые объекты, так и другие составные объекты.
Рис. 4. Дизайн шаблона Компоновщик.
Разберём пример использования шаблона Компоновщик. Пусть необходимо работать с картой, отдельные элементы которой реализуют интерфейс IComponent.
public interface IComponent
{
string Title { get; set; }
void Draw();
IComponent FindChild(string title);
|
|
}
public class MapComponent: IComponent
{
public string Title { get; set; }
public void Draw()
{
Console.WriteLine(Title);
}
public IComponent FindChild(string title)
{
return (Title == title)? this: null;
}
}
Применим класс MapComposite, чтобы «собрать» фрагменты карты.
public class MapComposite: IComponent
{
private readonly List<IComponent> _map = new List<IComponent>();
public string Title { get; set; }
public void AddComponent(IComponent component)
{
_map.Add(component);
}
public void Draw()
{
Console.WriteLine(Title);
foreach (IComponent component in _map)
{
component.Draw();
}
}
public IComponent FindChild(string title)
{
if (Title == title)
{
return this;
}
foreach (IComponent component in _map)
{
var found = component.FindChild(title);
if (found!= null)
{
return found;
}
}
return null;
}
}
Покажем, как используются описанные классы.
var district = new MapComposite {Title = "District"};
district.AddComponent(new MapComponent {Title = "House 1"});
district.AddComponent(new MapComponent {Title = "House 2"});
var city = new MapComposite {Title = "New city"};
city.AddComponent(district);
city.Draw();
var house = city.FindChild("House 1");
house.Draw();