К основному контенту

LotusScript. Реализация шаблона программирования Singleton

Использование шаблона Singleton (или Одиночка) зачастую очень полезна. По условиям этого шаблона подразумевается (гарантируется), что в контексте существует только один экземпляр класса и предоставляется только одна точка для получения доступа к этому экземпляру - отсюда и его название. В качестве примечания можно отметить, что на самом деле это не обязательно должен быть именно один экземпляр. Если говорить более общо, реализация данного шаблона должна гарантировать существование ограниченного (не памятью, а логикой) количества экземпляров класса.
В связи с наличием определенных ограничений языка LotusScript, являющимся основой для разработки классических приложений под клиент IBM Notes, реализация шаблона Singleton становится не самой тривиальной задачей. Речь идет о следующих ограничениях:
1. Класс не может иметь приватный (private) конструктор.
2. Класс не может иметь статических (static) методов
Вариантов реализации при таких ограничениях весьма скудное количество. Один из них основан на следующих постулатах:
1. Класс, являющийся одиночкой объявляется private (т.е. виден только в рамках библиотеки, в которой объявлен)
2. Получение экземпляра класса от точки доступа к нему происходит в потерей информации о типе. Проще говора будет возвращен Variant.
Примеры таких реализаций приведены здесь:
http://www.lotushints.com/2008/11/design-patterns-part-3-singleton-pattern/
и здесь:
http://www.nsftools.com/tips/LotusScriptSingleton.htm
Разница между ними только в способе организации точки доступа: через фабричную функцию или через класс-фабрику.
Подобная реализация вполне приемлема для версий IBM Domino Designer версий 7 и ниже, до появления интерфейса дизайнера основанной на Eclipse. Информация о пользовательских класса (их методах) и так не была доступна и работа с ними были сравнима с работой с типом Variant - вслепую.
Предлагаемая мной реализация (не претендую на исключительную новизну. но пока не встречал) основана на следующим:
1. Точка доступа - статическая фабричная функция, содержащая статическую переменную для хранению экземпляра-одиночки. Модификатор Static для функции говорит о том, что все переменные, определенных в этой функции, по-умолчанию будут статическими, т.е. не будут менять свое значение между вызовами функции - то что надо для "Одиночки".
2. Для защиты от несанкционированного инстанцирования через конструктор будем использовать приватную переменную библиотеки.
В общем случае код будет выглядеть следующим образом:
Private someSingleton As Boolean 'приватная переменная, препятствующая прямому вызову New

Сам класс:
Class SomeSingletonClass

Public Sub New()
If Not someSingleton Then
Error 5000, {Прямое инстанцирование запрещено. Используйте функцию GetSomeSingleton()} 'Код ошибки для примера
End If
End Sub
'Прочие методы

End Class

Функция для получения доступа к экземпляру:
Static Function GetSomeSingleton() As SomeSingletonClass
Static this As SomeSingletonClass
If this Is Nothing Then
someSingleton = True 'Поднимаем приватный флаг, позволяющий вызвать конструктор без ошибки
Set this = New SomeSingletonClass
someSingleton = False
End If
Set GetSomeSingleton = this
End Function

Некоторые комментарии и примечания:
1. В качестве названия функции можно использовать название класса. Чисто синтаксически вызов любого метода этого класса будет выглядеть как обращение к классу напрямую
2. Вместо функции можно использовать свойство (Static Property Get ...), но у меня иногда происходят ошибки области видимости, вероятно из-за кривости рук, поэтому мне удобнее использовать функцию
3. Авто проверка орфографии предложила заменить слово "кривости" в пред. пункте на "красивости", но решил этого не делать...
4. Исходя из определения модификатора Static, написание Static Function и Static this одновременно - избыточно. Достаточно одного из них, но мне так больше нравится.

Вот как-то так :) Приятного использования и до новых встреч! В следующем посте предполагаю продолжение серии о базовых компонентах Extension Library. Он уже в работе и, надеюсь, выйдет скоро.

Комментарии

Популярные сообщения из этого блога

Занимательные алгоритмы. Поиск цикла в односвязном списке

И снова про тараканов, которые иногда возникают в голове. Как-то раз, засыпая, я задумался на курьезными задачками из своей сферы деятельности (Lotus Notes), которые можно было бы задать на собеседовании, плавно перешел к воспоминаниям о своих первых собеседования, когда опыта работы еще не было. Опыт самих собеседований у меня не велик а места, где задавались действительно интересные задачи (а не задачки типа: написать сортировку массива любым известным способом) вообще равны одному - это ABBYY. Как минимум одна задачка в списке на знание и понимание классических алгоритмов, описанных в книге Дональда Кнута -  Искусство программирования .

Unit-testing object validation when validator has DI

Summary Unit test object validation when validator(s) has a dependency. For instance, we have some custom field and cross-field validators. Want to test their combination. Additionally some of validators have dependencies, injected through constructor or setters. You're not using property injection, right? Shortcut If you are just searching for an answer, here's the fast way: Declare CustomConstraintValidatorFactory that implements javax.validation.ConstraintValidatorFactory Override getInstance method and on facing your constraint validator class instantiate it Otherwise delegate validator construction to org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorFactoryImpl Build validator factory and provide it your CustomConstraintValidatorFactory Build validator, using that factory... Go to demo project on GitHub for details:  https://github.com/MrArtemAA/blog-demos/blob/master/test-validator-with-injection/src/test/java/ru/artemaa/d

Lotus Notes FAQ. 8/9 Eclipse. Как настроить уведомления о Sametime сообщениях

Н а написание данной "инструкцию" натолкнул мой коллега. Помню, первый раз сам долго искал, как отключить постоянно выпрыгивающие уведомления о новых сообщениях в Sametime. И так, речь идет о клиентах IBM Notes 8+ версии Standart (Eclipse based). Как настроить уведомления о Sametime сообщениях?