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