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

GrandM-Patterns_in_Java

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

;* * * Метод регистрирует получателя будущих

Bгidge _ 237

* /данных измерений от этого сенсора .

public void addStreamingSensorListener ( StreamingSensorListener listener)

//listeners . addElement (listener) ; addStreamingSensorListener ( StreamingSensorLi s tener)

/***Этот метод отменяет регистрацию получателя

*/будущих данных от этого сенсора .

public void removeStreamingSensorListener ( StreamingSensorListener listener)

/listeners/ . removeElement(listener) ;

/**

addSt re amingSensorLis tener ( StreamingSen sorListener)

* Этот метод асинхронно удаляет измеренные значения

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

public void run () while (true) (

int value ; try

value = consumer . readInt () ;

catch (IOException е)

//

Канал не работает, поэтому выходим из метода ,

/ /

что приводит к окончанию выполнения потока .

/ /

try

return;

for (int i=O ; i < listeners . size () ; i++) StreamingSensorListener listener; listener

=(StreamingSensorListener) listeners . elementAt (i) ;

 

 

 

/ / for

 

 

/ /

listener.procesSМ8asurement (value) ;

//

}

while

/ /

run ( )

c l a s s

StreamingSensor

238

Глава 7. Структурные шаблоны проектироваНИR

 

Чтобы класс StreamingSensor мог передавать измерение объекту, необходи­ мо, чтобы этот объект реализовывал интерфейс StreamingSensorListener. Измерения передаются методу processMeasurement, который объямен ин­

терфейсом StreamingSensorListener. Класс StreamingSensor тоже реали­ зует интерфейс StreamingSensorListener. Объекты реализации передают измерения экземплярам класса StreamingSensor, вызывая его метод pro­ cessMeasurement.

И наконец, приведем интерфейс, который соответствует классу Streaming­ Sensor:

interface StreamingSensorImpl extends SimpleSensorImpl (

/ * *Потоковые сенсоры выдают поток измеренных значений .

*Частота выдачи потока значений не превышает

*заданное количество раз в минуту . @param freq

* Максимальная частота (раз в минуту) выдачи результатов

*измерений данным потоковым сенсором .

*/

public void setSamplingFreguency (int freq)

throws SensorException ;

/ * *

*Данный метод вызывается объектом, представляющим абстракцию

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

*измеренных значений .

*@param abst raction Объект абстракции, которому передаются измеренные значения .

* /

public void setStreamingSensorListener (

StreamingSensorListener listener) ;

) / / interface StreamingSensorlmpl

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

Layered Architecture. Шаблон Bridge представляет собой способ организаЦИIt

сущностей (в виде классов), идентифицированных с помощью шаблона Layeгed

Architecture, описанноrо в работе [BMRSS96].

Bгidge _ 239

Abstract Factory. Шаблон Abstract Factory может использоваться шаблоном

Bridge для принятия решения о том, какой класс реализации нужно инстанции­ рОвзть для объекта абстракции.

раDecorator. Шаблон Decorator может использоваться для динамического выбо­

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

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

СИНОПСИС

Шаблон Facade упрощает доступ к связанному набору объектов, предоставляя

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

другими объектами, не принадлежащими этому набору объектов.

КОНТЕКСТ

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

мпля

 

класс MessageBody, экземпляры которого содержат тела сообщений;

ЮJaСС Attachment, экзе

ры которого содержат прилагаемую к сообщению

информацию, которая может быть присоединена к объекту MessageBody; класс MessageHeader, экземпляры которого содержат информацию для за­ головка - кому, от кого, тема (to, fют, subject) - сообщения электронной

почты;

класс Message, экземпляры которого связаны с объектом MessageHeader

и объектом MessageBody;

класс Security, экземпляры которого используются для добавления циф­

ровой подписи в сообщение;

класс MessageSender, экземпляры которого должны отправлять объектЫ

Message на сервер, отвечающий за доставку электронной почты по нужно­

му адресу или на другой сервер.

На рис. 7. 1 О представлена диаграмма классов, описывающая отношения меЖдУ

этими и клиентским классом.

Очевидно, что работа с такими классами электронной почты усложняет кли­

ентский класс. Чтобы применять эти классы, клиент должен иметь информа­

цию как минимум о шести классах, об отношениях меЖдУ ними и о порядке

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

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

Шаблон Facade предоставляет способ защиты клиентов классов, например. классов электронной почты, от всей сложности организации таких классоВ. Этот способ подразумевает наличие дополнительного объекта, который скры-

Facade - 241

.....

Создает

0,.-'1

.... т Содержи

 

 

1

I

 

Ciient

 

 

1

 

 

.....Создает

1

1

 

 

 

 

,

0..-

I

 

 

 

Attachment

 

 

I

 

 

 

 

 

 

Создает.....

0. .1

1

I

1

 

 

 

.....

 

 

 

 

Создает

 

 

 

 

Создает.....

 

 

.....

 

 

 

 

 

Создает

 

 

 

 

0. .1

 

I

I

1

I

Security

MessageSender

 

 

 

 

отправитель

1

....

 

 

 

 

Содержит

 

 

 

 

t1

ЩMessageBody

1.1

Содержит

11

1

1

Message

 

1

 

получатель

1

1.1

0. .*

1

1

11 MessageHeader

I

 

Содержит

1

 

 

 

Отправляет

 

Рнс. 7.10. Создание электронного письма

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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

I

Client

I

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

 

 

 

 

 

 

 

 

 

 

 

 

 

1

 

 

1

 

 

1

 

 

 

 

 

 

 

 

r-----

I

 

 

 

--------

Создает

 

 

 

 

 

 

1

MessageCreator I

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

.....

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

.....

 

 

 

 

 

 

.....

 

 

 

1

1

 

 

 

 

 

 

 

.....

 

Создает

 

 

 

 

 

 

 

 

 

 

Создает

 

0..*

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Создает

 

 

 

 

 

 

 

r-----0. . * Attachment·I

I

 

 

 

 

 

.....

 

 

 

1

 

 

 

 

 

 

 

0. .1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

I

Security

I

 

I

MessageSender

I

 

 

 

 

 

 

 

 

0. .1

 

 

 

 

 

 

оmравитель

....

 

Создает.....

....

 

 

 

 

 

 

1

 

Содержит

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Содержит

 

 

 

 

 

 

_ 1

I

t

1

 

 

 

M

 

 

_

ess

 

 

_,

L-

 

a

g

e

o

d..y:..

l1.

l 1

Содержит

1

11

1

М

essage

1

L---

 

 

 

 

 

1

Содерж

получательtо..

-

1

 

 

I '

 

 

 

 

L-__________

 

 

г=--L--------' ,

1

 

1

l MessageHeader I

ит

 

 

 

О

тправляет

____

Рнс. 7. 1 1 . Создание электронного письма с использованием шаблона Facade

242 Глава 7. Структурные шаблоны проектирования

На этой схеме та часть ЮIaсса Client, которая отвечала за взаимодеЙСТВие

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

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

МОТИВЫ

© МеЖдУ классами, реализующими абстракцию, и соответствующими кли­

ентскими классами существует множество зависимостей. Эти зависимости очень усложняют клиентские классы.

@) Нужно упростить клиентские классы, поскольку более простые классы по­ зволяют делать меньше ошибок. Кроме того, чем проще клиенты, тем тре­ буются меньшие усилия ДЛЯ использования классов, реализующих абстрак­ цию, при их изменении.

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

РЕШЕНИЕ

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

 

 

 

 

 

 

I

 

 

 

1

 

 

I

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

CLient

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

исПОЛl.зует....

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

*

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Facade

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

I

 

I

 

 

 

 

I

 

 

 

1-

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

I

I

 

 

 

 

 

 

 

 

 

 

I

 

 

 

 

 

 

I

 

 

 

 

 

 

 

I

 

 

i

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

I

 

 

 

 

 

 

 

 

 

 

I l - I

 

 

 

 

I

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

J

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

I

 

I

 

 

 

J

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

РНС. 7.12.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Шаблон Facade

 

 

 

 

 

 

 

 

 

 

Facade - 243

eT никакой необходимости в том, чтобы класс Facade являлся непроницаемым Барьером, отделяющим клиентские классы от классов, реализующих абстрак­ i1li Ю. Вполне достаточно (а иногда и лучще), если класс Facade просто будет i1редставлять собой задаваемый по умолчанию способ доступа к Функциональ­ости классов, реализующих абстракцию. Если некоторые клиенты должныMeTЬ прямой доступ к классу, реализующему абстракцию, то класс Facadeожет иметь метод, который возвращает ссылку на соответствующий объект реализации.

CНазнаТbIx чение класса Facade состоит в том, чтобы разрещить использование про­ клиентов, а не требовать их в обязательном порядке.

РЕАЛИЗАЦИЯ

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

внутренними классами класса Facade.

Иногда нужно изменить классы реализации , используемые объектом-фасадом D.ЛЯ согласования изменений реализуемой абстракции. Например (возвраща­ ясь к ситуации с электронной почтой, описанной в разделе «Контекст,», могут потребоваться разные наборы классов для создания сообщений, соответст­ вующих стандартам MIME, МАРI или Notes. Разные наборы классов реализа­

ций обычно требуют разных классов Facade . Можно скрыть от клиентских классов факт использования различных классов Facade, применяя щаблон Interface (см. гл. 4): определить интерфейс, который должны реализовывать все классы Facade, участвующие в создании электронной почты. Затем заста­

вить клиентские классы обращаться к классу Facade не прямым образом, а че­

рез интерфейс.

СЛЕДСТВИЯ

©

Если поместить класс-фасад между классами, реализующими абстракцию,

 

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

 

клиентских классов передадутся классу-фасаду. Клиентам объектов-фаса­

 

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

©

садом.

Шаблон Facade уменьшает или устраняет связь между клиентским классом

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

244 Глава 7. Структурные шаблоны проектирования

ПРИМЕНЕНИЕ В JAVA API

в j ava . net класс URL может служить примером шаблона Facade. Он обеспеМО­ чивает доступ к содержимому ресурсов, на которые указывают URL. Класс жет быть клиентом класса URL и использовать его для получения содержимого URL, не будучи осведомленным о множестве классов, находящихся за фасадданом-, который предоставляется классом URL. С другой стороны, чтобы послать ные на URL, клиент объекта URL может вызвать его метод openConnection, ко­ торый возвращает объект URLConnection, используемый объектом URL.

ПРИМЕР КОДА

Рассмотрим код для класса MessageCreator, представленноro на рис. 7. 1 1. Экземпляры класса Mes sageCreator используются для создания и отправле­ ния сообщений электронной почты. Он представлен здесь как типичный при­ мер класса Facade.

public class MessageCreator

// Константы, обозначающие тип создаваемых сообщений .

public final static int МIМE

=

1 ;

public final static int МAPI

2 ;

private Hashtaыle headerFields

= new Hashtaыl( ); ;

private RichText messageBody;

 

private Vector attachments =

new Vector () ;

private boolean signМessage ;

 

 

public MessageCreator (String to,

String

frorn,

String

subj e c t )

this (to, frorn , subject, inferмessageType (to» ; // Constructor (S tring, String, String)

public MessageCreator (String to , String frorn,

 

 

String subject , int

type)

 

headerFields . put ("to" ,

to) ;

 

 

headerFields . put ("frorn" , frorn) ;

 

 

headerFields . put ("subject" , subject) ;

 

/ * *

 

Str ing, String ,

int )

 

/ / Construc tor ( St ring,

* /

 

 

 

*

 

Задаем содержимое тела

сообще ния .

 

Facade - 245

public void setмessageBody (String messageBody) {

 

 

setмessaqeBody (new RichTextString (messageBody»

;

 

// setMessageBody ( S t ring)

 

/ * *

 

 

 

*/

Задаем содержимое тела сообщения .

 

*

 

 

public void setмessageBody (RichText messageBody)

{

 

this . messageBody = messageBody;

 

 

// setMessageBody ( RichText)

 

/**

 

 

 

*

/

Добавляем к сообщению присоединяемую информацию .

*

 

public void addAttachment (Object attachment)

 

 

attachments . addElement (attachment) ;

 

 

// addAttachment (Obj ect)

 

/**

 

 

 

*

 

Указываем,

будет ли сообщение подписано .

 

*/

Значение по

умолчанию - fals e .

 

*

 

 

public void setSign= Мessage (boolean signFlag) {

//signМessage signFlag; setSignMessage (boolean)

/**

*

*/Задаем значение для поля заголовка .

public void setHeaderField (String name , String value)

//headerFields . put (name . toLowerCase () , value) ;

/ * *

setHeaderField ( St ring, String)

*

*/Отправляем сообщение .

public void send() {

// send ( )

!46 Глава 7. Структурные шаблоны проектирования

/**

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

*/

private static= О ;int inferМessageType (String address) ( int type

return type;

)// inferMessageType ( String)

/** *

*/Создаем объект Secu rity, чтобы подписать это сообщение .

private Security= createSecurity () Security s null ;

/return/ в ; createSecu rity ( )

/**

*Создаем объект Mes sageSende r ,

соответствующий типу отправляемого сообщения .

*/

private void createМessageSender (Message msg) {

}// createMessageSender (Mes sage »

}// c l a s s Mes sageCreator

.llаблон Facade не предъявляет никаких требований к классам, которые

ICпользуются классом Facade. Поскольку они не добавляют ничего нового

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

lJАБЛОНЫ nРОЕКТИРОВАНИЯ, СВЯЗАННЫЕ

: ШАБЛОНОМ FACADE

nterface. Можно использовать шаблон lnterface вместе с шаблоном Facade. это

IOзволит применять различные классы фасадов, не требуя от клиентских к.лас­

..:овawосведомленности о разных классах.

оС Demeter. Концептуальная модель, применяющая шаблон Law of Demeter

описанный в книге [Grand99]), часто дает начало проекту, который использует uаблон Facade.

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