GrandM-Patterns_in_Java
.pdf208 • Глава 6. Разделяющие шаблоны проектирования
Чтобы программист не имел доступа к открытым методам, которые изменяют бин, необходимо снабдить его класс явной BeanInfo. Beanlnfo должна описы вать все свойства бина как предназначенные только для чтения. Кроме того,
она не должна обеспечивать какого-либо прямого доступа к тем методам, кото
рые изменяют содержимое бина.
СЛЕДСТВИЯ
© Использование шаблона Read-Only InterfaceТОМ, защищает от ошибок програм мирования, которые заключаются в что некоторые классы могут изме нять те объекты, которые не должны изменять.
®Шаблон Read-Only Interface не защищает объекты от ошибочного измене
ния в результате злонамеренного программирования. Чтобы защититься от
него, используйте шаблон Protection Proxy, описанный в книге [Grand2001).
ПРИМЕР КОДА
Пример кода для этого шаблона реализует часть проекта, представленноro в разделе «(Контекст» . Листинг класса TemperatureData :
public class TemperatureData implements TemperatureIF
private ArrayList listeners = new ArrayList () ;
/ * *
* Задает значение температуры, хранящееся в этом объекте .
* /
public void setTemperature (double temperature) this . temperature = temperature; fireTemperature () ;
}/ / setTernperature
/* *
* Воэвращает прочитанное значение температуры, * инкапсулированное в этом объекте .
* /
public double getTemperature ( ) return temperature ;
} / / ge tTernperature ( )
/* *
* Добавляем приемник в этот объект .
* /
Read-Only Interface - 209
public void addListener (TemperatureIF listener) ( listeners _ add (listener) ;
} / / addLi stener (Tempe ra ture IF)
/ * * * Удаляем приемник и з этого объекта .
* /
public void removeListener (TemperatureIF listener) (
listeners . remove (listener) ;
} / / removeLis tene r ( TemperatureIF)
/ * * |
|
|
|
* |
Отправляем TemperatureEvent |
всем |
|
* |
зарегистрированным объектам TemperatureListene r . |
||
* / |
|
|
|
private void fireTemperature () |
( |
||
|
int count = listeners . size ( ) ; |
||
|
TemperatureEvent evt; |
|
|
|
evt |
= new TemperatureEvent (this , temperature) ; |
|
|
for |
(int i = О ; i<count; i++) ( |
|
|
TemperatureListener thisListener |
||
|
|
= (TemperatureListener) listeners . qet (i) ; |
|
|
thisListener . temperatureChanqed (evt) |
||
|
} / / |
for |
|
// f i reTemperature ( )
// class TemperatureData
SensorController записывают значение температуры в объект Теm peratureData, вызывая его метод setTemperature. Считается, что никакой другой класс не может обращаться к методу setTemperature. С этой целью
другие классы осуществляют доступ к объектам TemperatureData через ин
терфейс TemperatureIF:
public interface TemperatureIF
/ * *
*Возвращает прочитанное значение температуры,
*инкапсулированное в этом объекте .
*/
public double getTemperature () ;
210 • Глава 6. Разделяющие шаблоны проектирования
/* *
* Добавляем приемник в этот объект .
* /
public void addListener (TemperatureIF listener)
/* *
* Удаляем приемник из этого объекта .
* /
public void removeListener (TemperatureIF listener)
/ / interface Temperature I F
Осталось отметить, что интерфейс TemperatureIF не имеет метода setTempe rature.
ШАБЛОНЫ nРОЕКТИРОВАНИЯ, СВЯЗАННЫЕ С ШАБЛОНОМ READ-ONLY INTERFACE
Interface. Шаблон Read-Only Interface использует шаблон Interface.
Protection Proxy. Шаблон Read-Only Interface не защищает от злонамеренного программирования. Шаблон Рюtесtiоп Рюху, описанный в книге [Grand2001], может использоваться для обеспечения доступа только для чтения к изменяе мому объекту в случае злонамеренного программирования. Правда, достигается это за счет дополнительных издержек ввиду сложности программирования и увеличения времени выполнения.
г А Л В Л
Структурные
шабnоныпроектирования
Adapter (Aдamep) (213)
Iterator (Итератор) (222) Bridge (Мост) (227) Facade (Фасад) (240)
F1yweight (Приспособленец) (248)
Dynamic Linkage (Динамическая компоновка) (260) Virtual Proxy (Виртуальный заместитель) (271) Decorator (Декоратор) (280)
СасЬе Management (Управление кэшем) (287)
Шаблоны , представленные в этой главе, описываютдля распространенные спосо
бы организации объектов разл ичных типов совместной работы.
Шаблон Adapter описывает, как у объекта может быть клиент, который предпо
лагает реализацию определен ного интерфейса, даже если клиент не реализует этот интерфейс.
кШаблон Iterator показывает, каким образом объект может осуществлять доступ
содержимому коллекции объектов, ничего не зная о структуре или классе этой коллекции .
Шаблон Bridge демонстрирует, как можно управлять п араллельн ы м и иерархия
МИ абстракций и реализаций .
Шаблон Facade описывает, каким образом можно сокрыть в одном объекте всю СЛожность, связанную с использованием группы связанных объектов.
fiaШ аблон Flyweight показывает, как можно избежать больш их расходов па мяти
многочисленные экземпляры некоторого объекта благодаря совместному
I1спользованию экземпляров, содержащих общие значения.
212 • Глава 7. Структурные шаблоны проектирования
Шаблон Dynamic Linkage демонстрирует способ динамического добавления
классов в программу на стадии выполнения.
Шаблон Virtual Рroху позволяет отложить на время создание объектов таким способом, который прозрачен для клиентов этих объектов.
Шаблон Оесогаtoг предназначен для динамического расширения или измене
ния поведения существующих объектов.
Шаблон Cache Management показывает, как можно избежать неоднократного
создания похожих объектов посредством многократного использования ранее
созданного объекта.
Этот шаблон был ранее описан в работе [GoF95].
СИНОПСИС
Класс-адаптер реализует интерфейс, известный его клиентам, и обеспечивает доступ к экземпляру класса, неизвестного его клиентам. Объект-адаптер пре
доставляет обещанную интерфейсом функциональностьдля , скрывая от клиента информацию о классе, используемом реализации этого интерфейса.
КОНТЕКСТ
Допустим, создается метод, который копирует массив объектов. Предполагается,
что этот метод должен отфильтровывать объекты, не удовлетворяющие опреде
ленному критерию, поэтому в копии массива будут содержаться не все элемен ты, находящиеся в исходном массиве. Для поддержки многократного исполь зования желательно сделать метод не зависящим от конкретного критерия фильтрации. Этого можно достичь, если задать интерфейс, объявляющий ме тод, который вызывается копировщиком массива с целью выяснения, будет ли данный объект включен в новый массив (рис. 7. 1).
|
|
Фильтр уетобъекты ДЛЯ него |
|
|
|
-I |
|
ArrayCopier |
.... |
|
|
«interface» |
|
|
-1 :1-----"",,;,,---------::. |
-:: __ |
||||
l |
|
|
0. 1 |
|
__ СОРУFiLtеГIF |
|
|
|
|
isCopyable(Object) : boolean |
MyCopyfilter isCopyable(Object) : boolean
Рис. 7.1. простой фильтр копирования
Класс ArrayCopier делегирует интерфейсу CopyFilterIF операцию принятия
решения, копировать ли в новый массив элемент старого массива. Если метод i SCopyable возвращает для объекта true, то этот объект копируется в новый
Массив. от
данный подход решает проблему, связанную с разрешением инкапсуляции в
дельном объекте критерия копирования, используемого объектами ArrayCopier.