Этот пример обсуждает, как приблизиться к разработке и реализации двух классов, которые взаимодействуют через события и прослушиватели. Эти два класса представляют банковский счет и менеджер учетных записей.
Чтобы спроектировать класс, который представляет банковский счет, сначала определите элементы данных и операции, которые формируют вашу абстракцию банковского счета. Например, банковский счет имеет:
Номер счета
Остаток на счете
Состояние (открытый, закрытый, и т.д.)
Необходимо выполнить определенные операции на банковском счете:
Создайте объект для каждого банковского счета
Внесите деньги
Заберите деньги
Сгенерируйте оператор
Сохраните и загрузите BankAccount
объект
Если баланс является слишком низким, и вы пытаетесь забрать деньги, банковский счет широковещательно передает уведомление. Когда это событие имеет место, банковский счет широковещательно передает уведомление другим сущностям, которые спроектированы, чтобы прислушаться к этим уведомлениям. В этом примере упрощенная версия программы менеджера учетных записей выполняет эту задачу.
В этом примере программа менеджера учетных записей определяет состояние всех банковских счетов. Эта программа контролирует остаток на счете и присваивает одно из трех значений:
open
— Остаток на счете является положительным значением
overdrawn
— Остаток на счете превышен ограничения, но на 200$ или меньше.
closed
— Остаток на счете превышен ограничения больше чем на 200$.
Эти функции задают требования BankAccount
и AccountManager
классы. Включайте только, какая функциональность требуется, чтобы достигать ваших определенных целей. Поддержите специальные типы учетных записей путем разделения на подклассы BankAccount
и добавление более определенных опций к подклассам. Расширьте AccountManager
как требуется поддерживать новые типы учетных записей.
Классы хранят данные в свойствах, реализуют операции с методами и поддерживают уведомления с событиями и прослушивателями. Вот то, как BankAccount
и AccountManager
классы задают эти компоненты.
Класс задает эти свойства сохранить номер счета, остаток на счете и состояние счета:
AccountNumber
— Свойство сохранить номер, идентифицирующий определенную учетную запись. MATLAB® присваивает значение этому свойству, когда вы создаете экземпляр класса. Только BankAccount
методы класса могут установить это свойство. SetAccess
атрибутом является private
.
AccountBalance
— Свойство сохранить текущий баланс учетной записи. Операция класса внесения и удаления денег присваивает значения этому свойству. Только BankAccount
методы класса могут установить это свойство. SetAccess
атрибутом является private
.
AccountStatus
— BankAccount
класс задает значение по умолчанию для этого свойства. AccountManager
методы класса изменяют это значение каждый раз, когда значение AccountBalance
падения ниже 0
. Access
атрибут задает это только AccountManager
и BankAccount
классы имеют доступ к этому свойству.
AccountListener
— Устройство хранения данных для InsufficentFunds
event.listener. Сохранение BankAccount
объект не сохраняет это свойство, потому что необходимо воссоздать прослушиватель при загрузке объекта.
Эти методы реализуют операции, заданные в формулировке класса:
BankAccount
— Принимает, что номер счета и начальный баланс создают объект, который представляет учетную запись.
deposit
— Обновляет AccountBalance
свойство, когда транзакция депозита происходит
withdraw
— Обновляет AccountBalance
свойство, когда транзакция вывода происходит
getStatement
— Информация об отображениях об учетной записи
loadobj
— Воссоздает прослушиватель менеджера учетных записей, когда вы загружаете объект из MAT-файла.
Программа менеджера учетных записей изменяет состояние банковских счетов, которые имеют отрицательные балансы. Реализовывать это действие, BankAccount
класс инициировал событие, когда вывод приводит к отрицательному балансу. Поэтому инициирование InsufficientsFunds
событие имеет место из withdraw
метод.
Чтобы задать событие, задайте имя в events
блок. Инициируйте событие вызовом notify
метод класса Handle. Поскольку InsufficientsFunds
не предопределенное событие, можно назвать его с любым char
вектор и триггер это с любым действием.
BankAccount
Реализация классаВажно гарантировать, что существует только один набор данных, сопоставленных с любым объектом BankAccount
класс. Вы не хотели бы независимые копии объекта, который мог иметь, например, различные значения для остатка на счете. Поэтому реализуйте BankAccount
класс как класс Handle. Все копии данного объекта указателя относятся к тем же данным.
BankAccount
Резюме класса
Класс BankAccount | Обсуждение |
---|---|
classdef BankAccount < handle
| Класс Handle, потому что должна быть только одна копия любого экземпляра |
properties (Access = ?AccountManager) AccountStatus = 'open' end |
|
properties (SetAccess = private) AccountNumber AccountBalance end properties (Transient) AccountListener end |
Смотрите задают Атрибуты свойств. |
events InsufficientFunds end | Класс задает событие под названием Для получения информации о событиях и прослушивателях, смотрите События. |
methods
| Блок обычных методов. Смотрите Задают Методы класса и Функции для синтаксиса. |
function BA = BankAccount(AccountNumber,InitialBalance) BA.AccountNumber = AccountNumber; BA.AccountBalance = InitialBalance; BA.AccountListener = AccountManager.addAccount(BA); end | Конструктор инициализирует значения свойств входными параметрами.
|
function deposit(BA,amt) BA.AccountBalance = BA.AccountBalance + amt; if BA.AccountBalance > 0 BA.AccountStatus = 'open'; end end |
Если |
function withdraw(BA,amt) if (strcmp(BA.AccountStatus,'closed')&& ... BA.AccountBalance < 0) disp(['Account ',num2str(BA.AccountNumber),... ' has been closed.']) return end newbal = BA.AccountBalance - amt; BA.AccountBalance = newbal; if newbal < 0 notify(BA,'InsufficientFunds') end end | Обновления Для получения дополнительной информации о прослушивателях смотрите Синтаксис Событий и Прослушивателей. |
function getStatement(BA) disp('-------------------------') disp(['Account: ',num2str(BA.AccountNumber)]) ab = sprintf('%0.2f',BA.AccountBalance); disp(['CurrentBalance: ',ab]) disp(['Account Status: ',BA.AccountStatus]) disp('-------------------------') end | Отобразите выбранную информацию об учетной записи. |
end methods (Static) | Конец обычного блока методов. Начало блока статических методов. Смотрите Статические методы |
function obj = loadobj(s) if isstruct(s) accNum = s.AccountNumber; initBal = s.AccountBalance; obj = BankAccount(accNum,initBal); else obj.AccountListener = AccountManager.addAccount(s); end end |
Для получения дополнительной информации о сохранении и загружаемых объектах, смотрите, Сохраняют и Процесс Загрузки для Объектов |
end end | Конец блока статических методов Конец |
AccountManager
КлассЦель AccountManager
класс должен предоставить услуги учетным записям. Для BankAccount
класс, AccountManager
класс прислушивается к выводу, который заставляет баланс заскакивать в отрицательную область значений. Когда BankAccount
возразите инициировал InsufficientsFunds
событие, AccountManager
сбрасывает состояние счета.
AccountManager
класс не хранит данных, таким образом, ему не нужны свойства. BankAccount
объектно-ориентированная память указатель объекта прослушивателя.
AccountManager
выполняет две операции:
Присвойте состояние каждой учетной записи в результате вывода
Добавляет учетная запись к системе путем контроля остатков на счетах.
AccountManager
класс реализует два метода:
assignStatus
— Метод, который присваивает состояние BankAccount
объект. Служит коллбэком прослушивателя.
addAccount
— Метод, который создает InsufficientFunds
прослушиватель.
AccountManager
КлассAccountManager
класс реализует оба метода как статические, потому что нет никакой потребности в AccountManager
объект. Эти методы работают с BankAccount
объекты.
AccountManager
не предназначается, чтобы быть инстанцированным. Разделение функциональности AccountManager
класс от BankAccount
класс обеспечивает большую гибкость и расширяемость. Например, выполнение так позволяет:
Расширьте AccountManager
класс, чтобы поддержать другие типы учетных записей при хранении отдельных классов учетной записи простыми и специализированными.
Измените критерии состояния счета, не влияя на совместимость сохраненного и загруженного BankAccount
объекты.
Разработайте Account
суперкласс, который факторизует то, что характерно для всех учетных записей, не требуя, чтобы каждый подкласс реализовал функциональность ведения счетов
AccountManager
Резюме класса
Класс AccountManager | Обсуждение |
---|---|
classdef AccountManager
| Этот класс задает |
methods (Static)
| Нет никакой потребности создать экземпляр этого класса, таким образом, заданные методы являются статическими. Смотрите Статические методы. |
function assignStatus(BA) if BA.AccountBalance < 0 if BA.AccountBalance < -200 BA.AccountStatus = 'closed'; else BA.AccountStatus = 'overdrawn'; end end end |
|
function lh = addAccount(BA) lh = addlistener(BA, 'InsufficientFunds', ... @(src, ~)AccountManager.assignStatus(src)); end |
|
end end |
|
BankAccount
класс, в то время как чрезмерно простой, демонстрирует, как классы MATLAB ведут себя. Например, создайте BankAccount
объект с номером счета и начальным депозитом 500$:
BA = BankAccount(1234567,500)
BA = BankAccount with properties: AccountNumber: 1234567 AccountBalance: 500 AccountListener: [1x1 event.listener]
Используйте getStatement
метод, чтобы проверять состояние:
getStatement(BA)
------------------------- Account: 1234567 CurrentBalance: 500.00 Account Status: open -------------------------
Сделайте вывод в 600$, который приводит к отрицательному остатку на счете:
withdraw(BA,600) getStatement(BA)
------------------------- Account: 1234567 CurrentBalance: -100.00 Account Status: overdrawn -------------------------
Вывод за 600$ инициировал InsufficientsFunds
событие. Текущие критерии, заданные классом AccountManager, приводят к состоянию overdrawn
.
Сделайте другой вывод в 200$:
withdraw(BA,200) getStatement(BA)
------------------------- Account: 1234567 CurrentBalance: -300.00 Account Status: closed -------------------------
Теперь AccountStatus
был установлен в closed
прослушивателем и дальнейшими попытками сделать вывод блокируются, не инициировав событие:
withdraw(BA,100)
Account 1234567 has been closed.
Если AccountBalance
возвращен в положительное значение депозитом, затем AccountStatus
возвращен, чтобы открыться, и вывод позволен снова:
deposit(BA,700) getStatement(BA)
------------------------- Account: 1234567 CurrentBalance: 400.00 Account Status: open -------------------------