Читайте также:
|
|
итерации. Представление текущего состояния каждой коллекции может быть любым, но оно полностью скрыто от клиентов. Решение, используемое в языке Dylan, можно написать на C++ следующим образом:
template <class Item> class Collection { public:
Collection();
IterationState* CreatelnitialState();
void Next(IterationState*);
bool IsDone(const IterationState*) const;
Item Currentltemfconst IterationState*) const;
IterationState* Copy(const IterationState*) const;
void Appendfconst Item&); void Remove(const Item&);
Операция CreatelnitialState возвращает инициализированный объект IterationState для коллекции. Операция Next переходит к следующему объекту в порядке итерации, по сути дела, она увеличивает на единицу индекс итерации. Операция IsDone возвращает true, если в результате выполнения Next мы оказались за последним элементом коллекции. Операция Cur rent It em разыменовывает объект состояния и возвращает тот элемент коллекции, на который он ссылается. Сору возвращает копию данного объекта состояния. Это имеет смысл, когда необходимо оставить закладку в некотором месте, пройденном во время итерации.
Если есть класс ItemType, то обойти коллекцию, составленную из его экземпляров, можно так:1
class ItemType { public:
void Process ();
Collection<ItemType*> aCollection; IterationState* state;
state = aCollection.CreatelnitialStatef);
while (laCollection.IsDone(state)) {
aCollection.Currentltem(state)->Process()
aCollection.Next(state); } delete state;
Отметим, что в нашем примере объект состояния удаляется по завершении итерации. Но оператор delete не будет вызван, если Processltem возбудит исключение, поэтому в памяти остается мусор. Это проблема в языке C++, но не в Dylan, где есть сборщик мусора. Решение проблемы обсуждается на стр. 258.
Паттерны поведения
У интерфейса итерации, основанного на паттерне хранитель, есть два преимущества:
а с одной коллекцией может быть связано несколько активных состояний (то же самое верно и для паттерна итератор);
а не требуется нарушать инкапсуляцию коллекции для поддержки итерации. Хранитель интерпретируется только самой коллекцией, больше никто к нему доступа не имеет. При других подходах приходится нарушать инкапсуляцию, объявляя классы итераторов друзьями классов коллекций (см. описание паттерна итератор). В случае с хранителем ситуация противоположная: класс коллекции Collection является другом класса IteratorState.
В библиотеке QOCA для разрешения ограничений в хранителях содержится информация об изменениях. Клиент может получить хранитель, характеризующий текущее решение системы ограничений. В хранителе находятся только те переменные ограничений, которые были преобразованы со времени последнего решения. Обычно при каждом новом решении изменяется лишь небольшое подмножество переменных Solver. Но этого достаточно, чтобы вернуть Solver к предыдущему решению; для отката к более ранним решениям необходимо иметь все промежуточные хранители. Поэтому передавать хранители в произвольном порядке нельзя. QOCA использует механизм ведения истории для возврата к прежним решениям.
Родственные паттерны
Команда: команды помещают информацию о состоянии, необходимую для отмены выполненных действий, в хранители.
Итератор: хранители можно использовать для итераций, как было показано выше.
Дата добавления: 2015-09-11; просмотров: 154 | Поможем написать вашу работу | Нарушение авторских прав |