Como posso remover / refatorar uma declaração de dependência de "amigo" corretamente?
O pano de fundo desta pergunta é baseado em um exemplo prático em que eu queria remover uma dependência de "amigo" de um par de classes usadas para gerenciar o acesso bloqueado de leitura / gravação a um recurso compartilhado.
Aqui está uma abstração do projeto estrutural original para esse cenário:
Marcado em vermelho, há essa dependência feia de "amigo" que quero remover do design.
Em resumo, por que eu tenho essa coisa aí:
ClassAProvider
compartilha uma referência a umClassA
através de um número de acessando simultaneamenteClient
instânciasClient
instâncias devem acessarClassA
somente através doClassAAccessor
classe auxiliar que gerencia os internosClassA
oculta todos os métodos destinados a serem utilizadosClassAAccessor
como protegido.assimClassA
pode garantir queClient
precisa usar umClassAAccessor
instânciaEsse padrão é útil principalmente quando se trata de garantir a saída de instâncias deClassA
em um estado definido, se umClient
falha na operação (por exemplo, por exemplo, uma exceção não capturada). ImagineClassA
fornecendo operações emparelhadas (visíveis internamente) comolock()
/unlock()
ouopen()
/close()
.
As operações de reversão (estado) devem ser chamadas em qualquer caso, especialmente quando um cliente falha devido a uma exceção.
Isso pode ser tratado com segurança através doClassAAcessor
Com o comportamento do ciclo de vida, a implementação do destruidor pode garantir isso. O diagrama de sequência a seguir ilustra qual é o comportamento pretendido:
Além dissoClient
instâncias podem obter um controle fino do acessoClassA
facilmente, apenas usando blocos de escopo C ++:
// ...
{
ClassAAccessor acc(provider.getClassA());
acc.lock();
// do something exception prone ...
} // safely unlock() ClassA
// ...
Tudo bem até agora, mas a dependência de "amigo" entreClassA
eClassAAccessor
deve ser removido por várias boas razões
The following table lists predefined standard elements for UML 1.x that are now obsolete. ... «friend» ...
A maioria das regras e diretrizes de codificação que eu vi proíbem ou desencorajam fortemente o uso de um amigo para evitar a forte dependência das classes de exportação para os amigos. Isso traz alguns problemas sérios de manutenção.Como diz o título da minha pergunta
Como posso remover / refatorar corretamente uma declaração de amigo (de preferência começando no design UML para minhas aulas)?