ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 11.12.2025

Просмотров: 3205

Скачиваний: 1

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

( q u e u e M e d i u m . C o u n t = = 0 ) & ( q u e u e L o w . C o u n t = = 0 ) ;

/}/ C o u n t - С к о л ь к о в с е г о э л е м е н т о в

p u b l i c i n t C o u n t / /

Р е а л и з у е м к а к

{

//

д л я ч т е н и я

 

g e t { r e t u r n q u e u e H i g h . C o u n t

+

 

q u e u e M e d i u m . C o u n t +

 

q u e u e L o w . C o u n t ;

}

в о в с е х о ч е р е д я х ?

}

 

с в о й с т в о т о л ь к о

 

}

}

/ / P a c k a g e

- пример

к л а с с а ,

который может быть р а з м е щ е н в

// о ч е р е д и с п р и о р и т е т а м и

 

c l a s s P a c k a g e : I P r i o r i t i z a b l e

{

 

 

 

p r i v a t e

P r i o r i t y

p r i o r i t y ;

/ / К о н с т р у к т о р

 

 

p u b l i c P a c k a g e ( P r i o r i t y

p r i o r i t y )

{

 

 

 

t h i s . p r i o r i t y =

p r i o r i t y ;

}

/ / P r i o r i t y - в о з в р а щ а е т п р и о р и т е т п а к е т а ; т о л ь к о д л я / / ч т е н и я

p u b l i c

P r i o r i t y

P r i o r i t y

 

 

g e t

{ r e t u r n p r i o r i t y ; }

 

 

}

 

 

 

 

/ / А также методы

T o A d d r e s s ,

F r o m A d d r e s s ,

I n s u r a n c e ,

/ / и

д р у г и е . . .

 

 

 

}

 

 

 

 

// К л а с с

P a c k a g e F a c t o r y опущен

- с м . полную

версию на

/ / п р и л а г а е м о м к о м п а к т - д и с к е

}

Демонстрационная программа P r i o r i t y Q u e u e несколько длиннее прочих демон­

страционных программ в книге, поэтому внимательно рассмотрите каждую ее часть.

Распаковка пакета

Класс P a c k a g e преднамеренно очень прост и написан исключительно для данной демонстрационной программы. Основное в нем — часть с приоритетом, хотя реаль ный класс P a c k a g e , несомненно, должен содержать массу других членов. Все, что требуется классу P a c k a g e для участия в данном пакете — это член-данные для хра­ нения приоритета, конструктор для создания пакета с определенным приоритетом и метод (реализованный здесь как свойство только для чтения) для возврата значения приоритета.

Требуют пояснения два аспекта класса P a c k a g e : тип приоритета и интерфейс

I P r i o r i t i z a b l e , реализуемый данным классом.

Оп р еделение возможных приоритетов

Приоритеты представляют собой перечислимый тип (enum) под названием Prior­ i t y . Он выглядит следующим образом:

352

Часть V. За базовыми классами


//Priority - в м е с т о ч и с л о в ы х п р и о р и т е т о в н а п о д о б и е 1, 2, // 3, . . . и с п о л ь з у е м п р и о р и т е т ы с именами

e n u m P r i o r i t y

{

Low, Medium, H i g h

{

Реализация интерфейса IPrioritizable

Любой объект, поступающий в P r i o r i t y Q u e u e , должен знать собственный при­ оритет (общий принцип объектно-ориентированного программирования гласит, что кажцый объект отвечает сам за себя).

Можно просто неформально убедиться, что класс P a c k a g e имеет член для получения его приоритета, но лучше заставить компилятор проверять это требование, т.е. то, что у любого объекта, помещаемого в P r i o r i t y Q u e u e , имеется этот член.

Один из способов обеспечить это состоит в требовании, чтобы все объекты реализовывали интерфейс I P r i o r i t i z a b l e :

// I P r i o r i t i z a b l e - о п р е д е л я е м п о л ь з о в а т е л ь с к и й и н т е р ф е й с :

//

классы,

к о т о р ы е

м о г у т

быть

д о б а в л е н ы в P r i o r i t y Q u e u e ,

II

должны

р е а л и з о в ы в а т ь

э т о т

и н т е р ф е й с

interface

I P r i o r i t i z a b l e

 

 

 

P r i o r i t y P r i o r i t y

{ g e t ;

}

 

 

Запись { g e t ; } определяет,

как должно быть описано свойство в объявлении

интерфейса. Обратите внимание, что тело функции доступа g e t отсутствует, но интерфейс указывает, что свойство P r i o r i t y — только для чтения и воз­ вращает значение перечислимого типа P r i o r i t y .

Класс

P a c k a g e

реализует интерфейс путем предоставления реализации свойства

Priority:

 

public

P r i o r i t y

P r i o r i t y

get {

r e t u r n

p r i o r i t y ; }

Функция Main()

Перед тем как приступить к исследованию класса P r i o r i t y Q u e u e , стоит посмот­ реть, как он применяется на практике. Вот исходный текст функции Main ( ) :

//Main

-

з а п о л н я е м

о ч е р е д ь

с п р и о р и т е т а м и

п а к е т а м и ,

// затем

и з в л е к а е м

из о ч е р е д и их с л у ч а й н о е

к о л и ч е с т в о

s t a t i c

v o i d Main ( s t r i n g [ ]

a r g s )

 

{

C o n s o l e . W r i t e L i n e ( " С о з д а н и е о ч е р е д и с п р и о р и т е т а м и : " ) ; P r i o r i t y Q u e u e < P a c k a g e > pq =

new P r i o r i t y Q u e u e < P a c k a g e > ( ) ;

C o n s o l e . W r i t e L i n e ( " Д о б а в л я е м с л у ч а й н о е к о л и ч е с т в о " +

 

Глава 15. Обобщенное программирование

353


" (0 - 20) случайных п а к е т о в " +

 

 

*

 

" в о ч е р е д ь : " ) ;

P a c k a g e p a c k ;

 

 

 

 

 

P a c k a g e F a c t o r y f a c t

=

new P a c k a g e F a c t o r y ( ) ;

//

Нам

нужно

с л у ч а й н о е

ч и с л о ,

меньшее 2 0

Random

r a n d =

new Random () ;

 

 

/ /

Случ айно е

ч и с л о

в

д и а п а з о н е

0 - 2 0

i n t n u m T o C r e a t e = r a n d . N e x t ( 2 0 ) ;

 

C o n s o l e . W r i t e L i n e ( " ^ С о з д а н и е

{0}

п а к е т о в : " ,

 

 

 

n u m T o C r e a t e ) ;

 

f o r ( i n t i = 0; i < n u m T o C r e a t e ; i + + )

{

C o n s o l e . W r i t e ( " \ t \ t T e H e p a u H H и д о б а в л е н и е " + " с л у ч а й н о г о п а к е т а { о } " , i ) ;

p a c k = f a c t . C r e a t e P a c k a g e ( ) ;

C o n s o l e . W r i t e L i n e ( " с п р и о р и т е т о м { о } " , p a c k . P r i o r i t y ) ;

p q . E n q u e u e ( p a c k ) ;

}

C o n s o l e . W r i t e L i n e ( " Ч т о п о л у ч и л о с ь : ") ; i n t n T o t a l = p q . C o u n t ;

C o n s o l e . W r i t e L i n e ( " П о л у ч е н о п а к е т о в : { о } " , n T o t a l ) ; C o n s o l e . W r i t e L i n e ( " И з в л е к а е м с л у ч а й н о е к о л и ч е с т в о " +

 

 

 

 

" п а к е т о в : 0-2 0 : " ) ;

i n t

numToRemove

=

r a n d . N e x t ( 2 0 ) ;

 

C o n s o l e . W r i t e L i n e ( " ^ И з в л е к а е м

{0}

п а к е т о в " ,

 

 

 

 

numToRemove);

 

 

f o r

( i n t i

= 0;

i

< numToRemove;

i + + )

{

 

 

 

 

 

 

 

p a c k = p q . D e q u e u e ( ) ;

 

 

 

i f

( p a c k

! = n u l l )

 

 

 

{

 

 

 

 

 

 

 

 

C o n s o l e . W r i t e L

 

 

i n e ( " \ t \ t Д о с т а в к а п а к е т а

 

 

 

 

" с

п р и о р и т е т о м {О}",

 

 

 

 

p a c k . P r i o r i t y ) ;

}

 

 

 

 

 

 

 

}

 

 

 

 

 

 

 

/ / С к о л ь к о п а к е т о в " д о с т а в л е н о "

 

 

C o n s o l e . W r i t e L i n e ( " Д о с т а в л е н о { о }

п а к е т о в " ,

 

 

 

 

n T o t a l - p q . C o u n t ) ;

/ / Ожидаем

п о д т в е р ж д е н и я

п о л ь з о в а т е л я

C o n s o l e . W r i t e L i n e ( " Н а ж м и т е < E n t e r > д л я " +

" з а в е р ш е н и я п р о г р а м м ы . . . " ) ;

C o n s o l e . R e a d ( ) ;

Итак, что же происходит в функции Main () ?

1. Инстанцируется объект P r i o r i t y Q u e u e для типа P a c k a g e .

2.Создается объект P a c k a g e F a c t o r y , работа которого состоит в формировании новых пакетов со случайно выбранными приоритетами. (Фабрика— это класс или метод, который создает для вас объекты.)

354

Часть V. За базовыми классами


3.Для генерации случайного числа используется класс Random из библиотеки

.NET, а затем вызывается P a c k a g e F a c t o r y для создания соответствующего

количества новых объектов P a c k a g e со случайными приоритетами.

4.Выполняется добавление созданных пакетов в P r i o r i t y Q u e u e с помощью вы­ зова p g . E n q u e u e ( p a c k ) .

5.Выводится число созданных пакетов, после чего некоторое случайное их количе­ ство извлекается из P r i o r i t y Q u e u e .

6.Функция завершается выводом количества извлеченных из P r i o r i t y Q u e u e па­ кетов.

Написание обобщенного кода

Как же написать собственный обобщенный класс со всеми этими <Т>? Выглядит это, конечно, устрашающе, но все не так уж и страшно.

Простейший путь написания обобщенного класса состоит в создании сначала его необобщенной версии, а затем расстановки в ней всех этих <Т>. Так, на­ пример, вы можете написать класс P r i o r i t y Q u e u e для объектов P a c k a g e , протестировать его, а затем "обобщить".

Вот небольшая часть необобщенного класса P r i o r i t y Q u e u e для иллюстрации ска­

занного:

 

 

 

 

 

 

public c l a s s

P r i o r i t y Q u e u e

 

 

 

{

 

 

 

 

 

 

//Queues

-

т р и в н у т р е н н и е ( о б о б щ е н н ы е ! )

о ч е р е д и

p r i v a t e 1

Q u e u e < P a c k a g e >

q u e u e H i g h

=

new

Q u e u e < P a c k a g e > ( ) ;

p r i v a t e

Q u e u e < P a c k a g e >

q u e u e M e d i u m

=

new

Q u e u e < P a c k a g e > ( ) ;

p r i v a t e

Q u e u e < P a c k a g e >

queueLow

=

new

Q u e u e < P a c k a g e > ( ) ;

//Enqueue - н а о с н о в а н и и п р и о р и т е т а P a c k a g e д о б а в л я е м е г о // в соответствующую о ч е р е д ь

p u b l i c v o i d E n q u e u e ( P a c k a g e i t e m )

{

s w i t c h ( i t e m . P r i o r i t y ) / / P a c k a g e и м е е т э т о с в о й с т в о

{

c a s e P r i o r i t y . H i g h :

q u e u e H i g h . E n q u e u e ( i t e m ) ; b r e a k ;

c a s e P r i o r i t y . L o w :

q u e u e L o w . E n q u e u e ( i t e m ) ; b r e a k ;

c a s e P r i o r i t y . M e d i u m :

q u e u e M e d i u m . E n q u e u e ( i t e m ) ; b r e a k ;

}

}

/ / и т а к д а л е е . . .

Написание необобщенного класса упрощает тестирование его логики. Затем, после тести­ рования и исправления всех ошибок, вы можете сделать контекстную замену P a c k a g e на <Т> (конечно, все не так прямолинейно, но и не очень отличается от сказанного).

355


Обобщенная очередь с приоритетами

Теперь пришло время разобраться с основным классом, из-за которого все и затева лось — с обобщенным классом P r i o r i t y Q u e u e .

Внутренние очереди

Класс P r i o r i t y Q u e u e — оболочка, за которой скрываются три обычных объекта Queue<T>, по одному для каждого уровня приоритета. Вот первая часть исходного тек ста P r i o r i t y Q u e u e , в которой показаны эти три внутренние очереди:

/ / P r i o r i t y Q u e u e

- обобщенный

к л а с с о ч е р е д и с п р и о р и т е т а м и ;

// типы данных,

д о б а в л я е м ы х в

о ч е р е д ь , о б я з а н ы

/ / р е а л и з о в ы в а т ь и н т е р ф е й с I P r i o r i t i z a b l e c l a s s P r i o r i t y Q u e u e < T >

w h e r e T : I P r i o r i t i z a b l e

{

/ / Q u e u e s - т р и в н у т р е н н и е ( о б о б щ е н н ы е ! ) о ч е р е д и

p r i v a t e

Queue<T>

q u e u e H i g h

=

new

Q u e u e < T > ( ) ;

p r i v a t e

Queue<T>

queueMedium

=

new

Q u e u e < T > ( ) ;

p r i v a t e

Queue<T>

queueLow

=

new

Q u e u e < T > ( ) ;

/ / Все

о с т а л ь н о е

м ы в о т - в о т

р а с с м о т р и м . . .

В данных строках объявляются три закрытых члена-данных типа Queue<Т>, ини­ циализируемые путем создания соответствующих объектов Queue<T>.

Метод Enqueue()

E n q u e u e О добавляет элемент типа Т в P r i o r i t y Q u e u e . Работа состоит в том, чтобы выяснить приоритет элемента и поместить его в соответствующую приоритету очередь. В первой строке метод получает приоритет элемента и использует конструкцию s w i t c h для определения целевой очереди исходя из полученного значения. -Например, получив элемент с приоритетом P r i o r i t y . H i g h , метод E n q u e u e () помещает его в очередь q u e u e H i g h . Вот исходный текст метода P r i o r i t y Q u e u e . E n q u e u e ():

//

Д о б а в л я е т э л е м е н т Т в о ч е р е д ь на о с н о в а н и и з н а ч е н и я е г о

/ /

п р и о р и т е т а

p u b l i c v o i d E n q u e u e ( Т i t e m )

{

 

 

s w i t c h ( i t e m . P r i o r i t y )

/ /

Т р е б у е т р е а л и з а ц и и

{

/ /

I P r i o r i t i z a b l e

c a s e P r i o r i t y . H i g h :

 

 

q u e u e H i g h . E n q u e u e ( i t e m ) ; b r e a k ;

c a s e P r i o r i t y . L o w :

q u e u e L o w . E n q u e u e ( i t e m ) ; b r e a k ;

c a s e P r i o r i t y . M e d i u m :

q u e u e M e d i u m . E n q u e u e ( i t e m ) ; b r e a k ;

d e f a u l t :

t h r o w new

A r g u m e n t O u t O f R a n g e E x c e p t i o n ( i t e m . P r i o r i t y . T o S t r i n g ( ) ,

356

Часть V. За базовыми классам