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

GrandM-Patterns_in_Java

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

176 Глава 5. Порождающие шаблоны проектирования

} // cons tructor (Class , CreationIF, i n t , i n t )

/**

* Возвращает количество объектов в пуле .

*/

public int getSize ( ) return size ;

}// getS i z e ( )

/**

*

Возвращает максимальное количество объектов,

*

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

*

использования .

*/

public int getcapacity ( ) return pool . length;

// ge tCapaci t y ( )

/ * *

*

Задает максимальное количество объектов,

*

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

*

использования .

*

@param newValue

*

*

Новое значение для максимального количества объектов ,

*

которые могут находиться в пуле . Это значение должно

*

быть больше нуля .

*/

public void setCapacity (int newValue) { if (newValue<=O) {

String msg = "Capacity must Ье greater than zero: " + newValue ;

throw new IllegalArgumentException (msg) ; / / i f

synchronized (lockObject) {

Object [ ] newPool = new Object[newValue] ;

System . arraycopy(pool , О , newPool , О , newValue) ; pool = newPool ;

// s ynchroni zed // setCapacity ( in t )

/**

*Возвращает из пула объект . При пустом пуле будет создан объект, если количество управляемых пулом

*объектов не больше или равно значению,

возвращаемому методом getMaxlnstance s .

*Если количество управляемых пулом объектов превышает это

*/значение , то данньм метод возвращает nul l .

puыlcc Object getObject () {

synchronized

(lockObject)

 

if (size>O) (

 

 

return

removeObject { ) ;

 

 

else if

(getInstanceCount { ) < getмAxInstances { » {

 

 

return

createObject {) ;

 

}

else (

 

 

 

// i f

null ;

 

//

return

//

synchroni zed ( l ockObj ect)

getObj ect ( )

/* .

* Возвращает из пула объект . При пустом пуле

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

*

объектов не больше или равно значению,

возвращаемому

методом getMaxlnstances .

 

Если количество управляемых пулом объектов превышает это

*

значение , то даннЬМ метод будет ждать

до тех пор, пока

*

какой-ни удь управляющий объект не станет доступным для

повторного использования .

 

*

@ throws

InterruptedException

 

*

Если

вызывающий поток был прерван .

 

*/

puыlcc Object waitForObject () throws InterruptedException { synchronized (lockObject)

if (size>O) (

return removeObjec () ;

else if (qetInstanceCount () < qetмaxInstances ( » { return createObject ( ) ;

else {

178 Глава 5. Порождающие шаблоны проектирования

do {

 

11

Ожидает извещения о том,

 

1 1

что объект был возвращен назад в пул .

 

 

wait ( ) ;

 

while (size<::O) ;

 

return removeObject ( ) ;

}

1 1 if

 

} 1 1

s ynchronized ( lockObject)

11waitForObj ect ( )

1* *

* Удаляет объект из пула и возвращает е го .

* 1

private Object removeObject ( ) { size-;

return pool [size) ;

11removeObj ect ( )

1* *

* Освобождает объект для пула с целью его повторного

* использования .

*

*@param obj

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

*@ throws ArrayStoreException

*Если данный объект не является экземпляром класса ,

*переданного конструктору объекта этого пула .

*@ throws Nul l PointerExcept ion

*Если данный объект равен nul l .

*/

public void release ( Object obj ) {

I lno

nul l s

 

if (

obj -- null )

{

throw new NullpointerException ( ) ;

/1

i f nu l l

 

synchronized (lockObject) {

if

(getSize () < getCapacity (»

 

pool [size]

:: obj ;

Objed Pool 179

 

 

 

//

size++ ;

 

 

 

 

 

Оповещаем ожидающий поток о том,

 

 

 

//

что мы поместили объект

в

пул .

 

 

 

/ /

i f

 

 

 

 

/ /

lockObject . notify () ;

 

 

/ /

//

synchronized

 

 

release ( )

 

 

class

Obj ectPool

 

 

А теперь приведем листинг интерфейса CreationIF.

/ * *

 

public interface CreationIF (

*

/

Возвращаем вновь созданный объект .

*

 

public Object create () ;

//

interface creationIF

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

СВЯЗАННЫЕ С ШАБЛОНОМ OBJECT POOL

СасЬе Management. Шаблон Cache Management управляет многократным ис­ пользованием определенных экземJUIЯРОВ класса. Шаблон Object Роо) управляет и создает экземпляры класса, которые могут использоваться как взаимозаме­ няемые.

Factory Method. Шаблон Factory Method может использоваться ДЛЯ инкапсуля­

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

сSяingleton. Объекты, которые управляют пулами объектов, обычно являют­

одиночками.

Thread Pool. Шаблон Thread Роо) (рассмотренный в книге [Grand99]) пред­

Ставляет собой специальную форму шаблона Object Роо).

L<x:k Object. Шаблон Lock Object может использоваться при реализации шаб­ Лона Object Роо).

г Л А В А

Разделя ющие

шаблоныпроектирования

FПtег (Фильтр) (182)

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

Read-Only Interface (Интерфейс, предназначенный только для чтения) (204)

Обшая стратегияII , призванная решать проблемы, может быть сформулирована

так: разделяй властвуй. Она предусматривает разбиение сложной проблемы,

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

облегчить создание хорошего проекта.

надШаблон Filter описывает, как удобно организовать вычисления, выполняемые

потоком данных.

Шаблон Composite помогает в создании иерархии объектов.

Шаблон Read-Only Interface описывает способы разделения классов, исполь­

ЗУЮмогутщих некоторый объект, причем те, которым разрешено изменять объект,

это делать, а те, которым не разрешено, - не MOгyr.

Этот шаблон был ранее описан в работе [BMRSS96].

СИНОПСИС

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

КОНТЕКСТ

,

Существует множество программ, целью которых является выполнение вычис­ лений над потоками данных и/или их анализ. Примером программы, совер­ шающей простые преобразования содержимого потока данных, может служить программа uniq в UNIX. Она организует свои входные данные в виде строк. Обычно программа uniq копирует все считываемые ею строки в свои BЫx0дf ные данные. Однако если она обнаруживает последовательные строки, содер­ жащие идентичные символы, то она копирует в свои выходные данные только первую такую строку. В UNIX есть также программа wc, которая выполня, простой анализ потока данных. Она вычисляет количество символов, слOJо! и строк в потоке данных. Компиляторы выполняют сложные серии преобраз ваний и анализируют на входе исходный код с uелью получения на выходе двot ичных данных.

Поскольку многие программы выполняют преобразования и анализ потоко!. данных, должна быть несомненная польза в том, чтобы определить классы, полняющие наиболее распространенные преобразования и анализ. Такие клаоL сы будут использоваться очень часто.

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

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

ти потока данных. Очевидно, что эти классы должны быть написаны так, чтобы допускать большую гибкость объединения их экземпляров друг с другом. ОдиН из способов осуществления такой гибкости предполагает задание общего ин· терфейса Д Л Я всех этих классов таким образом, чтобы экземпляр одного мог ис­

пользовать экземпляр другого, не заботясь о том, экземпляром какого класса

является объект (рис. 6.1).

 

 

 

 

 

 

 

 

 

 

 

Filter _ 1 83

 

 

 

Использует

 

 

«interface»

I

 

исполЬзуеТ....

---

-

 

 

 

 

 

г--------::--- ,

 

FiLterlF

,IE-----------=--- -..

 

 

Использует

 

]

 

I

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

I

 

 

 

 

 

 

 

 

 

 

 

 

I

 

 

_ _ _ _ _ _ _ _ _ _ _ _ _ - - - - ,е

 

 

IrI _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ II ---------- L ---------- .II

 

 

I

 

 

I

 

 

 

I

 

I

 

 

 

 

 

 

 

 

I

[

 

I

[ [

 

I

J

[

 

I

 

I

 

 

 

BufferFiLter

DecodeFiLter

LineCountFiLter I

 

 

 

 

 

 

 

,

 

 

,

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Рис. 6.1.

Фильтры данных

 

 

МОТИВЫ

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

©Должна существовать возможность динамического комбинирования объек­

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

©Использование объектов преобразования/анализа должно быть прозрач­ ным для других объектов.

РЕШЕНИЕ

Решение основано на использовании общих интерфейсов и делегирования.

Шаблон Filter организует свои классы в виде источников, приемников и фильт­

ров данных. Классы фильтров данных выполняют операции преобразования

и анализа. Существуют две основные формы шаблона Filter:

потоки данных, получаемые объектом приемника данных при вызове мето­

дов источника данных. эта форма шаблона Filter называется рull-формой;

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

даетданные методу объекта приемника. эту форму шаблона Filter называют push-формоЙ.

На рис. 6.2 представлена рull-форма шаблона Filter.

Опишем классы, участвующие в рull-форме шаблона Filter.

SourceIF. Интерфейс, выступающий в этой роли, объявляет один или не­ СI(ОЛько методов, которые в ответ на их вызов возвращают данные. На рис. 6.2 один такой метод имеет имя getData.

Source. Класс, выстynающий в этой роли, отвечает главным образом за пре­

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

роль, должны реализовывать интерфейс Sourc e I F.

184 Глава 6. Разделяющие шаблоны проектирования

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

((;nterface»

I

 

 

 

 

 

 

 

 

 

 

 

 

 

SourceF

 

 

 

...Получает данные

от

 

 

 

 

putDataO

 

 

 

 

 

 

 

4-

 

 

 

 

 

 

 

 

 

 

 

 

------ - - - - - - - -L . - - - - - - - - 1

 

 

 

 

 

 

 

 

 

AbstractPullFilter·

 

 

-....:....: -__

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Source

 

 

 

 

 

 

 

 

 

 

 

 

 

 

putData()

 

I

Sink

I

 

 

 

 

 

 

 

 

 

 

 

-sоurсе:SоuгсеIF

 

 

 

 

 

1

 

 

 

 

«constructor»

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

create(source:SourceIF)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

«misc»

 

 

 

 

 

 

 

 

......Получает данные от

 

putData()

 

 

 

 

 

 

 

 

 

 

 

 

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ConcretePullFilter

 

 

 

 

 

 

 

 

 

 

 

 

1

«constructor»

 

 

 

 

 

 

 

 

 

 

 

'-_____

 

create(source:SourceIF)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

«misc»

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

putDataO

 

 

 

 

 

 

 

 

Рис. 6.2. Рull-форма шаблона Filter

AbstractPullFilter. Класс, выступающий в этой роли, представляет собой абст­ рактный суперЮIaСС для классов, которые преобразуют и анализируют данные. Он имеет конструктор, в который передается объект SourceI F. Экземпляры этого класса делегируют выборку данных объекту SourceI F, который был пе­ редан их конструктору.

Классы AbstractPul l Fi lter обычно имеют переменную, которая ссылается на объект SourceI F, переданный их конструктору. Однако, чтобы обеспечитЬ независимость их подклассов от этой переменной экземпляра, она должна быть закрытой. Классы Abs tractPul l Fi lter обычно определяют метод getData,

который просто вызывает метод getData объекта SourceI F. на который ссы­ лается переменная экземпляра.

ConcretePullFilter. Класс, выступающий в этой роли, представляет собой кон­

кретный подкласс класса Abs tractPu l lFil ter. Они замещают унаследован­ ный ими метод getData С целью выполнения соответствующих операций пре­ образования или анализа.

Sink. Экземпляры классов, выступающих в этой роли, вызывают метод getData

объекта SourceSink I F. В отличие от объектов ConcretePul lFil ter экземплярыАЬ­

классов используют данные, не передавая их другому объекту s tractPul lFi l ter.

На рис. 6.3 представлена диаграмма классов для рush-формы шаблона Filter. :

Filter - 1 85

рассмотрим роли, выполняемые этими классами и интерфейсом.

SinkIF. Интерфейс, выступающий в этой роли, объявляет один или несколько методов, которые получают данные с помощью одного из параметров. На рис. 6.3

один такой метод имеет имя putData.

....Передает

.

1

 

I

 

Source

 

 

 

 

"'Передает

 

 

 

данные

 

 

 

 

 

 

 

 

 

 

 

 

«;nterface»

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

SinkIF

 

 

 

 

 

 

 

 

 

данные

 

 

 

 

getDataO

 

 

 

 

 

 

. . .

l:JI .

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

I- - - - - - - - - - - - - - - - - - - - - ---1

 

 

 

AbstradPushFilter

 

 

 

 

 

Sink

 

 

 

-sоuгсе:SоuгсеIF

 

 

 

 

 

 

 

 

 

 

 

getDataO

 

 

 

«constructorn

 

 

 

 

 

 

 

 

 

create(source:SourceIF)

 

 

 

 

 

 

 

 

 

«misc»

 

 

 

 

 

 

 

 

 

getDataO

 

 

 

 

 

 

 

 

 

. . .

 

 

 

 

 

 

 

 

 

1

 

 

 

 

 

 

 

 

 

 

 

ConcretePuchFiLter

 

 

 

 

 

 

 

1

((constructorn

 

 

 

 

 

 

 

 

 

create(source:SourceIF)

 

 

 

 

 

 

 

 

«misc»

 

 

 

 

 

 

 

 

 

 

getDataO

 

 

 

 

 

 

 

 

 

 

.. .

 

 

 

 

 

 

 

 

 

 

Рис. 6.3. Рush,форма шаблона Filter

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

ние и обработку данных, а не за их преобразование или анализ. Классы, играю­ щие эту роль, должны реализовывать интерфейс S i n k I F. Данные передаются

объектам Sink посредством их передачи методу putData этого объекта.

AbstractPushFlter. Класс, выступающий в этой роли, представляет собой абст­

рактный суперкласс Д Л Я классов, которые преобразуют и/или анализируют

данные. Он имеет конструктор, которому передается объект SinkIF. Экземп­ ЛЯры этого класса передают данные объекту SinkIF, который был передан их l1XКонструктору. Поскольку подклассы этого класса реализуют интерфейс SinkIF, экземпляры могут принимать данные от других объектов, которые передают

данные объектам SinkIF.

Классы AbstractPushFil ter обычно имеют переменную экземпляра, которая

ССылается на объект S inkI F, переданный их конструктору. Однако, чтобы

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

Должна быть закрытой. Классы AbstractPushFi l ter обычно определяют

186 Глава 6. Разделяющие шаблоны проектирования

метод putData, вызывающий метод putData объекта SinkI F, на который CCbl лается переменная экземпляра.

ConcretePushFilter. Класс, выступающий в этой роли, представляет собой кон­ кретный подкласс класса AbstractPushFi l ter. Они замещают унаследован­ ный ими метод putData с целью выполнения соответствующих операций пре_ образования или анализа.

Source. Экземпляры классов, выступающих в этой роли, вызывают метод putData объекта S i n k I F.

РЕАЛИЗАЦИЯ

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

Создание классов фильтров независимыми от программы, в которой они ис­ пользуются, повышает вероятность их многократного использования. Однако в некоторых случаях эффективность снижается, если фильтр не использует ин­ формацию, зависящую от контекста. Лучший выход в такой ситуации - ком­ промисс. Например, можно определить один или несколько интерфейсов, ко­ торые объявляют методы для предоставления объекту фильтра информации, зависящей от контекста. Если программа обнаруживает, что объект фильтра реализует один из таких интерфейсов, она может использовать этот интерфейс для предоставления фильтру дополнительной информации.

Заставляя методы putData или getData класса фильтра проходить через мето­ ды getData или putData их суперкласса, мы добавляем некоторые дополни­ тельные издержки. Эти дополнительныеNсложностиМ, совсем несложно устра­ нить. Если ваши классы работают на которая применяет технологию HotSpot компании Suп, то предлагаемая HotSpot оmимизация устранит почти все дополнительные издержки. Если ваши классы работают в среде, в которой не предусматривается оптимизация такого рода, существуют компиляторы, кО­

торые могут выполнить оптимизацию посредством встраивания (in-Iining) об­

ращений к методам getData или putData суперкласса.

СЛЕДСТВИЯ

©Часть программы, которая соответствует шаблону Filter, может быть разби­ та на набор источников, приемников и фильтров.

©Объекты-фильтры, не сохраняющие внутреннее состояние, могут быть ди­

намически заменены на стадии выполнения программы. Это свойство фильтров, не хранящих состояния, позволяет динамически изменять пове"I1­

дение и адаптировать его в соответствии с различными требованиями

стадии выполнения программы.

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