Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Шаблоны проектирования.pdf
Скачиваний:
79
Добавлен:
11.05.2015
Размер:
1.13 Mб
Скачать

Все готово к применению компонентов и их декораторов. Вначалесоздадим исходный компонент, а потом дополним его возможности, используя оба декоратора. Обратите внимание на то, что несколько декораторов могут независимо применяться к одному и тому же объекту, а также на то, что декоратор может декорировать объект, который уже декорирован.

// обыкновенный элемент

IElement element = new Element {Text = "Demo"}; element.Draw();

// декорирование отступом

IElement ei = new ElementWithIdent(element) {Ident = 4}; ei.Draw();

// дополнительное декорирование скобками

IElement eb = new ElementWithBrackets(ei); eb.Draw();

2.3. Заместитель (Proxy)

Шаблон Заместитель позволяет контролировать доступ к заданному объекту, перехватывая все вызовы к этому объекту и прозрачно замещая его. Ни интерфейс, ни функциональность замещённого объекта с точки зрения клиента не меняются. Данный шаблон часто используется, если необходимо упростить или оптимизировать взаимодействие с объектом, скрывая несущественные для конкретной задачи подробности реализации.

На рис 3. показан дизайн шаблона Заместитель. И заместитель Proxy, и класс замещаемого объекта Subject реализуют общий интерфейс ISubject. Заместитель может агрегировать замещаемый объект или порождать локальныеэкземпляры этого объекта при необходимости. Как правило, клиент не имеет прямого доступа к замещаемому объекту.

Client

<<interface>>

 

ISubject

 

+Request()

Proxy

Subject

+Request()

+Request()

Рис. 3. Дизайн шаблона Заместитель. Перечислим некоторые разновидности шаблона Заместитель:

9

Удалённый заместитель (remote proxy) обеспечивает связь с замещаемым объектом, который находится в другом адресном пространстве или наудалённой машине;

Виртуальный заместитель (virtual proxy) реализует создание замещаемого объекта только тогда, когда он действительно необходим;

Защищающий заместитель (protection proxy) проверяет, имеет ли вызы-

вающий объект необходимые для выполнения запроса права.

Рассмотрим примера реализации виртуального заместителя для оптимизации работы с большими изображениями.

public interface IImage

{

void Display();

}

public class RealImage : IImage

{

private readonly string _filename;

public RealImage(string filename)

{

_filename = filename; LoadImageFromDisk();

}

public void Display()

{

Console.WriteLine("Displaying " + _filename);

}

private void LoadImageFromDisk()

{

Console.WriteLine("Loading " + _filename);

}

}

public class ProxyImage : IImage

{

private RealImage _image;

private readonly string _filename;

public ProxyImage(string filename)

{

_filename = filename;

}

public void Display()

{

if (_image == null)

10

{

_image = new RealImage(_filename);

}

_image.Display();

}

}

Приведём клиентский код, работающий с виртуальным заместителем:

IImage image1 = new ProxyImage("HiRes_10MB_Photo1");

IImage image2 = new ProxyImage("HiRes_20MB_Photo2");

image1.Display();

// выполняется загрузка

image1.Display();

// загрузка не выполняется

image2.Display();

// выполняется загрузка

image2.Display();

//

загрузка не

выполняется

image1.Display();

//

загрузка не

выполняется

2.4. Компоновщик (Composite)

Шаблон Компоновщик позволяет упростить и стандартизировать взаимодействие между клиентом и группой объектов, представляющих древовидную структуру. Этот шаблон используется, если необходимо, чтобы клиент одинаково обращался как с составным объектом, так и с отдельными его частями.

Рассмотрим элементы шаблона Компоновщик (рис. 4). Интерфейс IComponent является общим для составных объектов и их частей. С точки зрения клиента все объекты являются экземплярами IComponent – клиент не различает составные объекты и их части. Класс Leaf представляет «неделимые» объекты (название взято по аналогии с наименованием элемента древовидной структуры). Класс Composite описывает составной объект, он может содержать как неделимые объекты, так и другие составные объекты.

<<interface>> IComponent

+Operation()

Leaf

Composite

 

-children:IComponent[0..*]

+Operation()

+Operation()

Рис. 4. Дизайн шаблона Компоновщик.

Разберём пример использования шаблона Компоновщик. Пусть необходимо работать с картой, отдельные элементы которой реализуют интерфейс

IComponent.

11

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;

}

12