Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

GrandM-Patterns_in_Java

.pdf
Скачиваний:
98
Добавлен:
14.03.2016
Размер:
8.88 Mб
Скачать

368 Глава 8. Поведенческие шаблоны проектирования

го источника события. Закрытые именованные классы-адаптеры применяются

для обработки событий, поведение которых не зависит от источника событий. Класс BanquetMedia tor объявляет переменные экземпляра, ссылающиеся На

единственный создаваемый им экземпляр своих закрытых адаптерных клас­

сов-адаптеров.

private ItemAdapter itemAdapter = new ItemAdapter () ;

Конструктор класса BanquetMediator объявляет и инстанциирует анонимный класс-адаптер, обрабатывающий событие, которое возникает в том случае, если

диалог открыт. Адаптер вызывает метод класса BanquetMediator, отвечающий

за инициализацию начальных состояний зарегистрированных компонентов GUI.

Banquetмediator () (

= new WindowAdapter ( )

WindowAdapter windowAdapter

 

public void windowOpened (WindowEvent е) {

 

initialstate () ;

 

} ;

} / / windowOpened (WindowEvent)

 

 

BanquetReservationDialog enclosingDialog ; enclosingDialog = BanguetReservationDialog . this ; enclosingDialog . addWindowListener (windowAdapter) ;

/ / Cons tructor ( )

Класс I temAdapter представляет собой закрытый класс-адаптер, который оп­

ределот яется и используется классом BanquetMediator для обработки событий обеих кнопок-переключателей диалогового окна. Когда объект ItemAdapter

получает ItemEvent, он вызывает метод enforcelnvariants класса BanquetMe­ diator. Этот метод является для класса BanquetMediator основным. Метод enforcelnvariants активизирует все инвариантные отношения между компо­

нентами диалога. Он вызывается в ответ на получение собьггия от всех компонен­

тов GUI-диалога.

private class ItemAdapter implements ItemListener public void itemStateChanged (ItemEvent е)

enforceInvariants () ;

} / / i temStateChanged ( I temEvent)

} / / class I temAdapter

Метод, отвечающий за появление объекта кнопки ОК весьма прост, так каК

класс BanquetMedi ator не отвечает за обработку событий от этой кнопки. Он отвечает только за то, должна ли быть доступна или недоступна кнопка Ок.

Mediator 8 369

public void registerOkButton (JВutton ok) { okButton = ok ;

/ / registerOkButton ( JButton)

Методы регистрации других объектов GUI более сложны, так как они затраги­ вают управление специальными событиями ДЛЯ объектов, зарегистрированных

в определенной роли. Управление специальными событиями необходимо ДЛЯ

того, чтобы проверить содержимое отдельных объектов GUI. Следующий ме­

тод регистрации более типичен. Он регистрирует поле, предназначенное ДЛЯ

ввода количества участников предстоящего банкета.

public

void registerPeopleCountField (final JТextComponent field) { peopleCountField = field;

DocumentAdapter docAdapter = new DocumentAdapter () {

protected void parseDocument ( ) int count = PEOPLE_COUNТ_DEFAULT; try {

String countText = field. getText () ; count = Integer . parseInt (countText) ; catch (NumberFormatException е) {

if (MIN_PEOPLE<=count

"

count<=МAX PEOPLE

peopleCount =

count;

else

 

 

peopleCount =

PEOPLE_COUNT_DEFAULT;

} ; ) / /

pars eDocument ( )

Document doc = field . getDocument () ; doc . addDocumentListener (docAdapter) ;

/ / registerPeopleCountField (JTextComponen t )

Этот метод регистрации создает анонимный объект-адаптер, который не про­ сто вызывает метод enforce l nvariants. Об этом позаботился анонимный

суперкласс-адаптер. Перед тем как вызвать метод enforce l nvariants объекта

BanquetMediator, супеРКJIaСС вызывает свой собственный метод parseDocu­ rnent. Класс анонимного адаптера его замещает, устанавливая переменную эк­

земпляра peopleCount объекта BanquetMediator. Если поле, соответствую­ Щее количеству человек, намеревающихся посетить банкет, содержит правильное Зliачение, то адаптер это значение записывает в peopleCount. В противном

СЛучае в peopleCount задается специальное значение, информирующее метод enforcelnvariant о том, что в поле количества человек, намеревающихся по­

Сетить банкет, введена неправильная величина.

370 Глава 8. Поведенческие шаблоны проектирования

Методы регистрации других текстовых полей работают аналогичным образом.

Они создают объект-адаптер, который проверяет правильность введенного

вполе значения, устанавливает переменную экземпляра в некоторое значеНие

изатем вызывает метод enforce I nvariants.

Метод enforceI nvariants может изменять состояние некоторых компонен­

тов GUI, чтобы заставить их удовлетворять некоторым инвариантным оТНоше­

ниям. При этом компоненты генерируют события. Объект BanquetMediator

при помощи своих адаптеров получает некоторые из этих событий. Когда ком­

понент GUI отвечает на одно из изменений состояния, сделанных методом enforceI nvariants, и передает событие одному из объектов-адаптеров Вап­ quetMediator, он рекурсивно вызывает метод enforceI nvariants. Чтобы

избежать бесконечной рекурсии, класс BanquetMediator использует флаг,

указывающий на рекурсивные обращения к методу enforce I nvariants.

private boolean busy = false i

private void enforcelnvariants () if (busy)

returni busy = true i

protectedEnforcelnvariants () i busy = false i

/ / enfo rce lnva riants ( )

Как видно, метод enforce Invariants активизирует инвариантные отноше­ ния непрямым образом. Если он вызывается рекурсивно, происходит немед­ ленный возврат этого метода. В противном случае он вызывает метод protec­ t edEn force I nvariants.

Метод enforce Invar iants определяет рекурсивные обращения так: сначала

проверяет, а затем устанавливает значение переменной busy. Поскольку мо­

дель управления событием в языке Java гарантирует синхронную передачу со­

бытий, метод enforceInvariants не должен быть вызван для управления не­

которым событием в то время, как он все еще обрабатывает другое событие.

В подобной ситуации методдолжен быть синхронизирован в соответствии с се­

мантикой обрабатываемых им событий.

Приведем инвариантные отношения, активизируемые методом protected­

Enforce Invar iants.

Поля Date, Start Time и End Time разрешены тогда и только тогда, когда

поле Number of People содержит разрешенное значение.

Если кнопки-переключатели запрещены, их состояние не позволяет их вы­

бирать.

Список блюд доступен тогда и только тогда, когда доступны поля Data, Start

 

Time и End Time и выбран переключатель Buffet (Шведский стол) или ТаЫе

Mediator - 371

(Обслуживание за столиками). Правильное время окончания банкета должно

быть по крайней мере на один час позднее, чем время начала.

Кнопка ОК доступна тогда и только тогда, когда доступен список блюд и из списка выбрано хотя бы одно блюдо.

private void protectedEnforceInvariants ( )

/ /

Если задано

количество человек, переменная enable

/ /

должна иметь

значение t rue .

boolean enable

=(peopleCount ! = PEOPLE_COUNТ_DEFAULT) ;

/ /

Поля Data , Start Tirne,

End Tirne , переключатели Buffet,

//

ТаЫе доступны тогда и

толь ко тогда , когда в поле,

//предназначенном для количества человек,

// содержится разрешенное значение . dateField. setEnabled (enable) ; startField. setEnabled (enable) ; endField. setEnabled(enable) ; buffetButton . setEnabled(enable) ; tableServiceButton . setEnabled(enable) ;

if (enable)

{

 

 

/ /

Список блюд доступен тогда и тол ь ко

тогда ,

/ /

когда

поля даты,

времени или кнопки-переключатели

/ /

доступны, и время

окончания по крайней мере

/ /

на один час больше времени начала ,

и выбран

/ /

переключатель Bu ffet или ТаЫе .

 

enable =

(buffetButton . isSelected ()

 

 

I

I

tableServiceButton . isSelected (»

 

 

 

 

 

 

foodList . setEnabled(enable

 

 

"

 

endAtLeastOneHourAfterStart (»

 

else

 

{

 

 

 

/ /

Если поля даты или времени или кнопки-переключатели

/ /

недоступны, то список блюд тоже должен быть

/ /

недоступен .

 

 

foodList . setEnabled(false) ;

 

/ /

Кнопки-переключатели недоступны, поэтому они не

/ /

могут быть выбраны .

 

buffet8utton . setSelected (false) ;

 

tableServiceButton . setSelected (false) ;

 

/ /

Если доступны, то

 

 

"foodList. qetмinSelectionIndex () >-1) ;

// protectedEnforce lnvariants ( )okButton . setEnabled(foodList . isEnabled()

372 Глава 8. Поведенческие шаблоны проектирования

Классы-посредники часто имеют внугренние вспомогательные методы, кото­

рые дополняют логику основного метода активизации инварианта. РазмещеНие некоторой части логики во вспомогательных методах способствует тому, что

размеры основного метода активизации инварианта позволяют легко управлять

им. Следующий метод возвращает true, если поля Date, Start Time и End Time

содержат допустимые значения и время в поле End Time как минимум на один

час больше времени в поле Start Time.

private boolean endAtLeastOneHourAfterStart ( )

Calendar startCalendar = getStartCalendar ( ) ;

if (startCalendar ==

null)

return

false ;

= getEndCalendar () ;

Calendar

endCalendar

if (endCalendar == null) return false ;

startCalendar . add (Calendar . MINUTE , 59) ; return getEndCalendar () . after (startCalendar) ;

} / / endAtLeas tOneHourAfterStart ( )

ШАБЛОНЫ ПРОЕКТИРОВАНИЯ, СВЯЗАННЫЕ С ШАБЛОНОМ MEDIATOR

Adapter. Классы Medi ator часто используют объекты-адаптеры для получения извещений об изменении состояния.

Interface. Шаблон Mediator использует шаблон Interface с целью поддержки независимости классов Col league от класса Mediator.

Low Coupling/High Cohesion. Шаблон Mediator - это хороший пример исклю­

чения из тех рекомендаций, которые выдаются шаблоном Low Coupling/Нigh

Cohesion (описанным в книге [Grand99]).

Observer. Шаблон Observer представляет собой значительную часть модели де­

легирования событий в языке Java. Если необходимо использовать шаблон

Mediator в таком контексте, в котором, по мнению программиста, модель деле­

гирования событий в языке Java не может быть использована, то можно ис­

пользовать для замены шаблон Observer.

Controller. Шаблон Controller (описанный в книге [Grand99]) позволяет опре­

делить, какой объект должен обрабатывать внешнее событие. Шаблон Mediator

помогает реализовать обработку событий.

White Бох Testing. Использование шаблона Mediator приводит в результате

к меньшему количеству ветвей выполнения кода. Это значит, что требуетсЯ

меньше усилий для тестирования программы при помощи шаблона White ВО)(

Testing, описанного в книге [Grand99].

Этот шаблон частично основан на шаблоне Memento, описанном в работе

[GoF95].

СИНОПСИС

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

КОНТЕКСТ

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

Во время этой игры пользователь заставляет героя вступать во взаимодействие

с различными действуюшими лицами, контролируемыми компьютером, и объек­

тами, смоделированными компьютером. Программа может завершаться смертью

героя, управляемого игроком.

Среди многочисленных свойств игры есть две характеристики, которые пред­ полагают сохранение и восстановление состояния игры. Эти свойства очень

необходимы программе, поскольку, если играть в такую игру до ее полного за­

вершения, на это потребуется несколько дней непрерывной игры.

Чтобы позволить игроку делать многочисленные перерывы во время игры, должна существовать возможность сохранения состояния игры в файле,

чтобы позднее ее можно было продолжить.

Чтобы довести игру до конца, пользователь должен успешно провести сво­ его героя через множество приключениЙ. Если герой, руководимый игро­ ком, умирает, игрок имеет возможность начать игру с самого начала. Но та­ кой вариант не всегда является наилучшим, поскольку игрок уже хорошо

освоил игру и много раз проходил все предыдущие этапы. Лучше, чтобы

программа предложила игроку вариант возобновления игры с момента, предшествующего смерти героя.

е этой целью сохраняется часть состояния игры, включающая накоплен­ ный ранее опыт героя и запись некоторых его достижений. Частичное со­ хранение состояния будет производиться в тот момент, когда герой выпол­

нит какое-то важное задание. В ходе игры такие контрольные точки стано­

вятся частью полного состояния игры, они должны сохраняться при записи на диск остальной части состояния.

37..Глава 8. Поведенческие шаблоны проектирования

ХОТЯ в игре участвует множество классов, рассмотрим только некоторые ИЗ

них, которые несут обшую ответственность за создание моментальных снимков

состояния игры (рис. 8.14).

 

 

 

 

 

 

использующий

 

 

 

 

 

 

 

....считывает байты

 

 

1 : FileInputStream1

 

 

 

 

 

 

байты

 

 

J,

 

 

 

 

 

 

J,

 

1

 

 

 

 

 

 

 

 

выдающий байты

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

 

 

 

 

 

 

 

 

 

 

 

 

 

I

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Использует

 

 

Deserializer

 

 

 

 

 

 

I

FileOutputStreaml

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

 

байты

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

десериализирует....

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

......Записывает

 

 

использующий

 

--i

 

 

 

 

 

,

1

 

 

 

 

1

J

 

Serializes

, 1

 

байты в

 

 

 

 

 

 

 

 

 

 

 

UserInterface

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

"'

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

,

Использует

 

 

 

 

, выдающий байты

 

 

 

 

 

 

 

 

 

 

 

 

1

 

 

 

 

 

 

 

 

 

 

 

 

 

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Использует

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

сериализирует....

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

If

 

 

 

 

 

 

 

оБыIлIIющийй класс

 

 

 

 

 

 

1 ...

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

,

 

 

 

 

 

 

 

 

 

 

 

 

 

GameModel

 

 

 

 

--

------

---- -

---

,,

 

....Использует

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

- ----

 

 

 

 

 

 

 

 

 

 

 

createMemento(description:String):MilestoneMementoIF

 

 

 

 

 

 

 

 

 

 

 

 

setMemento(:MilestoneMementoIF)

 

 

 

 

 

 

 

 

 

 

 

80сстанавли- ......1

 

 

 

 

 

1

 

 

 

 

 

 

 

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

вает состояние

 

 

Оповещает....

 

 

 

 

 

 

 

......Запраwивает создание

 

 

 

 

 

 

 

 

 

,

 

из

Milestone

 

 

о контрольных

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Memento

1

 

 

отметках

 

1

 

 

 

 

 

 

 

1

 

 

 

 

Milestone Memento

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

MilestoneMementoManager

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

V

 

 

 

 

 

 

snapshotMilestonе(description:String)

 

 

 

 

 

 

 

 

 

---- -- - - --- -- - t>1

 

 

 

 

 

 

 

getMilestoneMementos( ):MilestoneMementoIF

«interface»

 

 

 

 

 

 

 

restoreFromMemento(:MilestoneMementoIF)

- -

Serializable

 

 

 

 

 

 

 

 

 

 

1.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

яВляется....

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

MilestoneMemento -

 

 

 

 

 

 

.

м

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

зто закр

ытый статический

 

,

 

 

 

закрыты

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

классом-

 

,

 

 

 

 

0. • *

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

класс-член класса

 

 

 

 

 

членом

 

 

 

 

 

 

 

«interface»

 

 

 

 

<J-

 

 

 

GameModel

 

 

 

 

 

 

 

зтого класса

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

MilestoneMementoIF

 

 

---

 

---

---- -- --------

«static»

 

 

 

 

 

 

 

 

 

 

 

 

 

 

-

 

 

 

-

 

 

 

 

 

 

 

 

 

 

 

MilestoneMemento l - :

 

 

 

 

getDescription( ):String

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Рис. 8.14.

 

Классы моментального. снимка игры

'

 

 

 

 

 

 

 

ОТ­

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Данные классы принимают участие в двух различных механизмах:

 

 

 

сохранения части СОСТОЯНИЯ игры,

когда герой достигает контрольной

 

метки;

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

сохранения и восстановления всей игры целиком.

 

 

 

 

 

 

 

 

 

 

 

Классы

Userl nter face

И GameModel участвуют в обоих механизмах.

 

 

 

 

 

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

Snapshot 375

UserInterface. Все предпринимаемые игроком действия проходят через класс

User lnterface.

Класс Userlnterface передает большую часть действий, инициируемых игро­ ком, экземпляру класса GameModel . Однако в процессе работы с инициируе­ мыми игроком моментальными снимками игры задействованы и другие подхо­ ды, которые будут рассмотрены ниже.

GameModel. Класс GameModel отвечает за поддержание состояния программы во время сеанса игры. Класс Userlnterface оповещает экземпляр класса GameMode l , если игрок делает что-то связанное с игрой. Экземпляр класса GameModel определяет последствия этого действия, соответствующим образом изменяет состояние игры и оповещает пользовательский интерфейс. Кроме того, экземпляр класса GameModel может сам инициировать некоторые дейст­

вия. Он всегда сообщает о последствиях любого инициированного им действия пользовательскому интерфейсу, но не всегда - о самом действии.

Участие класса Userlnterface в процессе создания моментального снимка состоит в том, что он инициирует один вид моментального снимка и оба вида

восстановления. Класс GameModel отвечает за состояние игры, поэтому он дол­ жен участвовать в любой операции, манипулирующей состоянием игры.

Опишем другие классы и интерфейсы, принимающие участие в сохранении и восстановлении частичного состояния.

MilestoneMemento. Класс Mi lestoneMemento - это закрытый класс, опреде­

ляемый классом GameModel . Объект GameMode l создает экземпляры класса Mi lestoneMemento, содержащие копии значений, которые определяют сохра­ няемое частичное состояние. Имея объект MilestoneMemento, объект GameModel может восстановить свое предьшущее состояние, содержащееся в объекте

Mi lestoneMemento.

MilestoneMementoIF. Этот интерфейс является открытым и реализуется клас­ сом Miles toneMemento. За пределами класса GameModel доступ к экземпля­

рам класса MilestoneMemento может быть осуществлен только как к экземп­

лярам класса Obj ect или через интерфейс Mi lestoneMementoIF. Ни один режим доступа не позволяет объекту обращаться к информации о состоянии,

инкапсулированной в объектах Mi lestoneMemento.

МilestoneMementoManager. Класс MilestoneMementoManager вносит свой вклад

в процесс принятия решения о создании объектов MilestoneMemento. Он так­

Же управляет их использованием после того, как они были созданы.

Приведем описание записи частичного состояния игры, происходящего после i1o. ro, как управляемый игроком герой достиг контрольной метки.

2.Существует объект MilestoneMementoManager, связанный с каждым объек­ том GameMode l . Когда объект GameMode l принимает состояние, соответст-

376 Глава 8. Поведенческие шаблоны проектирования

вующее моменту достижения контрольной отметки, он вызывает метод s napshotMilestone связанного с ним объекта MilestoneMementoManager.

Метод snapshotMiles tone передает методу строку, в которой содержится описание контрольной метки. Управляемый игроком герой мог ранее уЖе быть у этой контрольной метки, умереть и затем возвратиться к предьщу_ щей контрольной метке. Если объект MilestoneMemento для некоторой контрольной метки уже существует, то для этой контрольной метки не дол­ жен создаваться другой объект Mi les toneMemento.

З. Объект Mi les toneMementoManager определяет, существует ли уже объект Miles toneMemento для контрольной отметки, сравнивая строку описания, переданную его методу snapshotMi lestone, с описаниями уже сушест­

вующих объектов MilestoneMemento. Если объект MilestoneMemento

с данным описанием уже существует, то метод snapshotMi les tone не предпринимает никаких дополнительных действий.

4.Если объект Miles toneMementoManager определяет, что для контрольной

отметки еще не сушествует объект MilestoneMemen to, то объект МНе­ stoneMementoManager инициирует создание объекта Mi lestoneMemento

ДЛЯ записи частичного состояния игры в данный момент. При этом он вы­ зывает метод createMemento объекта GameMode l, передавая ему то же са­ мое описание, которое он передавал объекту Miles toneMementoManager.

5.Метод createMemento возвращает вновь созданный объект Miles tone­ Memento, который объект MilestoneMementoManager добавляет в свою

коллекцию объектов Mi lestoneMementoIF.

Если руководимый игроком герой умирает, объект UserI nterface предлагает игроку снова включиться в игру не с самого начала, а с последней пройденной

контрольной отметки. Он предлагает игроку сделать выбор из списка коюроль­

HbIX

отметок,

вызывая метод getMi lestoneMementos объекта Mi les tone­

то

 

составляет

 

 

MementoManager. Этот метод возвращает массив объектов Mi lestoneMemento,

ко рый

 

 

коллекциюсобранную,

объектом MilestoneMementoManager .

Если игрок указывает, что он хочет, чтобы герой возобновил игру от одной из

ранее ПРОЙденных контрольных отметок, объект User Interface передает со­

ответствующий объект MilestoneMemento методу restoreFromМemento объ­ екта MilestoneMementoManager. Этот метод в свою очередь вызывает метоД setMement o объекта GameMode l, передавая ему выбранный объект МНе­

s toneMemento. Объект GameModel восстанавливает свое состояние, используя

информацию, находящуюся в этом объекте MilestoneMemento.

При использовании другого механизма моментального снимка в файле сохра­

няется полное состояние игры, включая объект Mi lestoneMementoManager

и его коллекцию объектов Mi lestoneMemento. Этот механизм основан на

средстве сериализации языка Java.

В процессе сохранения (восстановления) в файл (из файла) моментальноГО снимка полного состояния игры участвуют следующие классы.

Snapshot _ 377

Serializer. Класс Seria l i zer отвечает за сериализацию объекта GameMode l. ОН копирует в файл (представляя в виде байтового потока) информацию о со­ стоянии объекта GameMode l и других объектов, на которые он ссылается и ко­

торые являются частью состояния игры.

FileOutputStream. Это стандартный класс Java под названием j

а

v

а .

iо . Fi­

leOutputStream, который записывает байтовый поток в файл.

 

 

Deserializer. Класс Deserial izer отвечает за чтение сериализованного байто­ вого потока и создание копии объекта GameModel и других объектов, которые были сериализованы.

FileInputStream. Это стандартный класс языка Java под названием j ava . i o . Fi­ lelnputStream, который читает байтовый поток из файла.

Опишем последовательность событий для ситуации, когда пользователь от­ правляет запрос на сохранение игры в файл или восстановление ее из файла.

1 . Игрок сообщает пользовательскому интерфейсу, что он хочет сохранить

игру в файле. Тогда объект Userlnterface создает объект Seriali zer, пе­ редавая его конструктору имя файла и ссылку на объект GameMode l. Объект

Serial i zer создает объект Obj ectOutputStream и объект FileOut ­ putStream. Serial i zer исполь1 зует объект Obj ectOutputS tream для се­ риализации объекта GameMode и всех других связанных с игрой объектов, на которые он ссылается. Для записи этого байтового потока в файл он ис­ пользует объект Fi leOutputStream.

2. Когда игрок хочет восстановить игру из файла, он сообщает об этом пользо­ вательскому интерфейсу. Тогда объект Userlnterface создает объект Ое­ seriali zer, передавая его конструктору имя файла и ссьmку на объект

GameMode l . Объект Deserializer создает объект Obj ect l nputStream и объект F i l e l nputStream. Он использует объект F i l e l nputStream для чтения сериализованного байтового потока из файла. Для десериализации из байтового потока объекта GameMode1 и всех других связанных с игрой объектов, на которые он ссылается, объект Deser i a l izer использует объ­ ект Obj ectl nputStream.

Почти все приводимые в этой книге шаблоны описывают только один способ решения проблемы. Шаблон Snapshot отличается от них тем, что предоставляет

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

МОТИВЫ

©Нужно сделать моментальный снимок состояния объекта и, кроме того,

иметь возможность восстанавливать состояние объекта.

©Необходимо, чтобы механизм сохранения и восстановления объектов не за­

висел от внутренней структуры объекта и поэтому такая внутренняя струк­ тура могла бы изменяться, не нуждаясь в изменении механизма сохране­ ния-восстановления.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]