Предыстория этого вопроса основана на практическом примере, где я хотел удалить зависимость "друга" из пары классов, которые используются для управления доступом для чтения/записи с заблокированным доступом к общему ресурсу.
Здесь абстракция исходного структурного проекта для этого сценария:
Отмечено красным цветом, вот эта уродливая зависимость "друга", которую я хочу удалить из дизайна.
Короче говоря, почему у меня есть эта вещь:
-
ClassAProvider
делится ссылкой наClassA
на несколько одновременный доступ к экземплярамClient
-
Client
экземпляры должны получить доступ кClassA
только черезClassAAccessor
вспомогательный класс который управляет внутренними элементами. -
ClassA
скрывает все методы, предназначенные для использования сClassAAccessor
как защищенные. - Итак
ClassA
может гарантировать, чтоClient
должен использовать экземплярClassAAccessor
Этот шаблон в первую очередь полезен, когда он обеспечивает сохранение экземпляров ClassA
в
если выполняется операция Client
(из-за неперехваченного исключения). Думать о
ClassA
обеспечение (внутренне видимых) парных операций, таких как lock()
/unlock()
или open()
/close()
.
В любом случае следует вызывать операции (state-) reverseing, особенно когда клиент вылетает из строя
к исключению.
Это можно безопасно обрабатывать с помощью поведения ClassAAcessor
жизненного цикла, деструктора
реализация может обеспечить его.
Следующая диаграмма последовательности иллюстрирует то, что предполагаемое поведение:
Кроме того, экземпляры Client
могут легко получить прекрасный контроль доступа к ClassA
, просто используя
Блоки областей С++:
// ...
{
ClassAAccessor acc(provider.getClassA());
acc.lock();
// do something exception prone ...
} // safely unlock() ClassA
// ...
Все до сих пор хорошо, но зависимость "friend" между ClassA
и ClassAAccessor
должна быть удалена по ряду веских причин.
- В надстройке UML 2.2 в разделе C.2 в разделе "Изменения из предыдущего UML" говорится:
The following table lists predefined standard elements for UML 1.x that are now obsolete. ... «friend» ...
- Большинство правил и рекомендаций по кодированию, которые я видел, запрещают или сильно препятствуют использованию друга, чтобы избежать жесткой зависимости от классов экспорта для друзей. Эта вещь вызывает некоторые серьезные проблемы с обслуживанием.
Как говорится в названии вопроса
Как правильно удалить/реорганизовать объявление друга (желательно, начиная с дизайна UML для моих классов)?