Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Шаблоны и архитектура программ.doc
Скачиваний:
12
Добавлен:
04.05.2019
Размер:
558.08 Кб
Скачать

Приспособленец (Flyweight)

Шаблон Приспособленец предлагает эффективный способ разделить общую информацию, находящуюся в небольших объектах. Основная проблема – в затратах на хранение таких объектов, если их число велико, а содержащаяся информация дублируется. В качестве примера рассмотрим программу для просмотра фотографий с возможностью отнесения фотографии к одной из групп. Если окно приложения показывает несколько групп фотографий, может возникнуть проблема производительности (размер фото достаточно велик), а также проблема дублирования информации (одна фотография принадлежит нескольким группа).

Рассмотрим диаграмму шаблона Приспособленец (рис. 7).

Рис. 7. Диаграмма шаблона Приспособленец.

Суть шаблона в том, чтобы разделить состояние некоторого объекта на состояния трех типов. Внутреннее состояние (intrinsic state) принадлежит самому объекту. Тип Flyweight реализует интерфейс IFlyweight, который определяет операции, в которых заинтересована остальная часть системы. Клиент владеет общим (неразделяемым) состоянием (unshared state), а также коллекцией приспособленцев, которых производит класс-фабрика (FlyweightFactory). Наконец, внешнее состояние (extrinsic state) не появляется в системе как таковое. Если оно понадобится, то будет вычислено уже во время выполнения программы для каждого внутреннего состояния.

Отметим некоторые нюансы реализации шаблона Приспособленец. Тип Flyweight может быть реализован в виде структуры – он небольшой и ни от чего не наследует. Фабрика приспособленцев создает объекты в соответствии со специальными требованиями: нужно проверить, существует ли объект, и если не существует, то создать его и добавить во внутреннюю коллекцию-словарь.

using System;

using System.Collections.Generic;

public class CharacterFactory

{

private readonly Dictionary<char, Character> chars =

new Dictionary<char, Character>();

public Character GetCharacter(char key)

{

if (!chars.ContainsKey(key))

{

switch (key)

{

case 'A':

chars.Add(key, new CharacterA());

break;

case 'B':

chars.Add(key, new CharacterB());

break;

}

}

return chars[key];

}

}

public abstract class Character

{

public char Symbol { get; set; }

public int Width { get; set; }

public int Height { get; set; }

public int PointSize { get; set; }

public abstract void Display(int pointSize);

}

public class CharacterA : Character

{

public CharacterA()

{

Symbol = 'A';

Height = 100;

Width = 120;

}

public override void Display(int pointSize)

{

PointSize = pointSize;

Console.WriteLine("{0} (pointsize {1})", Symbol, PointSize);

}

}

public class CharacterB : Character

{

public CharacterB()

{

Symbol = 'B';

Height = 100;

Width = 120;

}

public override void Display(int pointSize)

{

PointSize = pointSize;

Console.WriteLine("{0} (pointsize {1})", Symbol, PointSize);

}

}

public class FlyweightExample

{

private static void Main()

{

// создаём "документ" с текстом

var document = "AABBAB";

var chars = document.ToCharArray();

var f = new CharacterFactory();

// pointSize - это внешнее состояние

var pointSize = 10;

// используем для каждого символа объект-приспособленец

foreach (var c in chars)

{

pointSize++;

var character = f.GetCharacter(c);

character.Display(pointSize);

}

}

}