- •А.А. Волосевич
- •3. Шаблоны и архитектура программ
- •3.1. Модульное тестирование
- •3.2. Шаблоны проектирования
- •3.3. Структурные шаблоны: Декоратор, Заместитель, мост Декоратор (Decorator)
- •Заместитель (Proxy)
- •Мост (Bridge)
- •3.4. Структурные шаблоны: компоновщик и приспособленец Компоновщик (Composite)
- •Приспособленец (Flyweight)
- •3.5. Структурные шаблоны: адаптер и фасад Адаптер (Adapter)
- •Фасад (Façade)
- •3.6. Порождающие шаблоны: прототип, фабричный метод, одиночка Прототип (Prototype)
- •Фабричный метод (Factory method)
- •Одиночка (Singleton)
- •3.7. Порождающие шаблоны: абстрактная фабрика и строитель Абстрактная фабрика (Abstract factory)
- •Строитель (Builder)
- •3.8. Шаблоны поведения: стратегия, состояние, шаблонный метод Стратегия (Strategy)
- •Состояние (State)
- •Шаблонный метод (Template method)
- •3.9. Шаблоны поведения: цепочка обязанностей и команда Цепочка обязанностей (Chain of responsibility)
- •Команда (Command)
- •3.10. Шаблоны поведения: итератор, посредник, наблюдатель Итератор (Iterator)
- •Посредник (Mediator)
- •Наблюдатель (Observer)
- •3.11. Шаблоны поведения: посетитель, интерпретатор, хранитель Посетитель (Visitor)
- •Интерпретатор (Interpreter)
- •Хранитель (Memento)
- •3.12. Некоторые неклассические шаблоны проектирования
- •Неизменный объект (Immutable object)
- •Пул объектов (Object pool)
- •Отложенная инициализация (Lazy initialization)
- •Нулевой объект (Null object)
- •3.13. Антипаттерны
- •3.14. Архитектура прогРаммного Обеспечения
- •«Клиент-сервер»
- •Архитектура, основанная на использовании компонентов
- •Многоуровневая архитектура
- •Шина сообщений
- •Выделенное представление
- •Объектно-ориентированная архитектура
- •Архитектура, ориентированная на сервисы
Приспособленец (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);
}
}
}