Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Тема-05-04.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
79.84 Кб
Скачать

5.4.2. Организация взаимодействия объектов

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

Определение сигнатур метода

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

Public Function AddEmployee(ByVal LogonName As String, . . .) As Integer

'Код записи информации в базу данных

. . . End Function

Public Sub Login(ByVal LogonName As String, . . . )

'Код считывания информации из базы данных

. . . End Sub

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

Передача параметров

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

Если параметр передается по значению, сервер (в данном случае – функция) получает копию фактического значения переменной; при этом в функции создается локальная переменная. В слу­чае изменения ее значения сервер должен передать копию назад клиенту, а тот принять решение: вносить изменения в оригинальный файл или игнорировать их. Здесь можно провести аналогию с работой отдела кадров. При необходимости обновить информацию о сотрудниках отдел кадров не выдает им на руки личные дела, а предоставляет копии тех документов, которые нужно изменить или дополнить. Выполнив эту задачу, сотрудники должны отправить копии назад, а отдел кадров, получив ответ, решает: вносить изменения в оригинал или нет. Этот способ работы с документами является достаточно эффективным и безопасным с точки зрения сохранения конфиденциальности.

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

Public Function AddEmployee(ByRef LogonName As String, ...) As Integer

'Код сохранения данных в базе данных

End Function

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

Управление событиями

В Windows система обработки сообщений – это фундаментальная структура, используемая для распространения информации в многозадачной среде. С точки зрения приложения сообщение является уведомлением о произошедшем событии, на которое программа должна (или не должна) каким-то образом отреагировать. Сообщение, которое передается всем приложениям, носит название широковещательного, а то, которое пересылается только заинтересованным приложениям и объектам, оформившим на него подписку, именуется распространяемым по подписке.

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

В VB.NET события являются членами класса и должны быть объявлены в его определении. Интерфейс процедуры обработки события сходен с подпрограммой, которой вы можете передавать параметры в виде сообщения. Для вызова события нужно применить оператор RaiseEvent. Ниже показано, как определяется и вызывается событие в серверном классе.

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

Public Class Data

Public Event DataUpdate(ByVal Msg As String)

Public Sub SaveInfo() Try

RaiseEvent DataUpdate(“Данные были обновлены") Catch

RaiseEvent DataUpdate(“Данные не могут быть обновлены") End Try End Sub

End Class

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

Перехват и обработка события в клиентском классе

Public Class Form2

Inherits System.Windows.Forms.Form Dim WithEvents oData As Data

Private Sub oData_DataSaved(ByVal Msg As String) _

Handles oData.DataUpdate MsgBox(Msg) End Sub

Private Sub btnSave_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles btnSave.Click oData = New Data() oData.SaveInfo()

End Sub

End Class

Делегаты

Делегирование – механизм, который применяется при обработке запросов, направляемых серверу. По своей структуре делегат является объектом, содержащим ссылку на метод. При делегировании сервер перенаправляет принятый запрос методу, который будет его обрабатывать. Класс, получивший полномочия, может проверить запрос и во время его выполнения определить, куда он должен быть перенаправлен. Примеры делегирования легко найти и в повседневной жизни. Вспомним аналогии между работой объектно-ориентированного приложения и действиями людей в реальном мире. Когда менеджер компании получает запрос, он часто делегирует ряд своих полномочий рядовому сотруднику отдела. Фактически каждый квалифицированный менеджер

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

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

Delegate Function CompareInt(ByVal i1 As Integer, ByVal i2 As Integer) _As Boolean

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

Использование делегатов

Private Function AscendOrder(ByVal i1 As Integer, _

ByVal i2 As Integer) As Boolean If i1 < i2 Then Return True End If End Function

Private Function DescendOrder(ByVal i1 As Integer, _

ByVal i2 As Integer) As Boolean If i1 > i2 Then Return True End If End Function

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

Public Sub SortIntegers(ByVal SortDirection As SortType, _

ByVal intArray() As Integer)

Dim CheckOrder As CompareInt

If SortDirection = SortType.Ascending Then

CheckOrder = New CompareInt(AddressOf AscendOrder)

Else

CheckOrder = New CompareInt(AddressOf DescendOrder)

End If

'Продолжение кода ...

End Sub

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

Использование делегатов в обработчиках событий

Еще один способ создания обработчиков событий – применение оператора AddHandler, имеющего два параметра: имя обрабатываемого события и имя делегата, который это делает. При­веденный ниже код демонстрирует использование указанного оператора для обработки события DataUpdate класса Data, определенного в листинге 4.14.

Использование делегата в обработчике событий

Public Class Form1

Inherits System.Windows.Forms.Form

Private Sub Save_click(ByVal sender As System.Object. _

ByVal e As System.EventArgs) Handles btnSave.Click Dim oData As Data = New Data()

AddHandler oData.DataUpdate, AddressOf oData_DataUpdate oData.SaveInfo() End Sub

Private Sub oData_DataUpdate(ByVal Msg As String)

MsgBox(Msg)

End Sub

End Class

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