O que é uma boa estratégia para vincular objetos de exibição a objetos de modelo em C ++?

5

Imagine que eu tenha um modelo de dados rico, representado por uma hierarquia de objetos.

Eu também tenho uma hierarquia de visões com visões que podem extrair dados necessários de objetos de modelo e exibir os dados (e permitir que o usuário manipule os dados).

Na verdade, pode haver várias hierarquias de exibição que podem representar e manipular o modelo (por exemplo, uma visão geral de detalhes e uma exibição de manipulação direta).

Minha abordagem atual para isso é que a camada do controlador armazene uma referência ao objeto de modelo subjacente no objeto View. O objeto de exibição pode, então, obter os dados atuais do modelo para exibição e enviar as mensagens do objeto de modelo para atualizar os dados. Os objetos de exibição são efetivamente observadores dos objetos de modelo e os objetos de modelo transmitem notificações quando as propriedades são alteradas.

Essa abordagem permite que todas as visualizações sejam atualizadas simultaneamente quando qualquer visão altera o modelo.

Implementado com cuidado, tudo isso funciona. No entanto, é necessário muito trabalho para garantir que nenhum objeto de visualização ou modelo contenha referências obsoletas a objetos de modelo. O usuário pode excluir objetos de modelo ou sub-hierarquias do modelo a qualquer momento. Garantir que todos os objetos de exibição que contêm referências aos objetos do modelo que foram excluídos consuma tempo e sejam difíceis.

Parece que a abordagem que estou tomando não é especialmente limpa; Embora não seja necessário ter código explícito na camada do controlador para mediar a comunicação entre as visualizações e o modelo, parece que deve haver uma abordagem melhor (implícita) para estabelecer ligações entre a exibição e o modelo e entre objetos modelo relacionados.

Em particular, estou procurando uma abordagem (em C ++) que entenda dois pontos-chave:

  1. Existe uma relação de muitos para um entre objetos de exibição e de modelo
  2. Se o objeto modelo subjacente for destruído, todos os objetos de visualização dependentes deverão ser limpos para que não existam referências obsoletas

Enquanto shared_ptr e weak_ptr podem ser usados para gerenciar os tempos de vida dos objetos do modelo subjacente e permitem referências fracas da visão para o modelo, eles não fornecem notificação para a destruição do objeto subjacente (eles fazem no sentido que o uso de um obsoleto weak_ptr permite a notificação), mas eu preciso de uma abordagem que notifique os objetos dependentes de que sua referência fraca está desaparecendo.

Alguém pode sugerir uma boa estratégia para gerenciar isso?

    
por B.J. 26.07.2013 / 05:05
fonte

3 respostas

3

Esteja ciente de que você está descrevendo com precisão o padrão de design observador , considerando que o objeto do modelo de domínio é o assunto e as visões para serem observadores. Note também que o padrão observador implica um nível mais alto de abstração do que um ponteiro inteligente, e que não há correspondência conceitual direta entre os dois.

Para implementar este padrão, você deve primeiro garantir que todas as visões envolvidas (observadores) implementem uma interface comum, por exemplo, herdando uma classe comum de base abstrata. Em seguida, o objeto de domínio (assunto) pode prosseguir com o gerenciamento de um conjunto de referências a instâncias da referida interface do observador e notificá-las todas quando necessário, chamando os métodos de interface apropriados.

Os ponteiros inteligentes podem ser usados neste esquema para implementar as referências gerenciadas pelo assunto.

    
por 27.09.2013 / 12:31
fonte
0

Bem, você sempre pode criar seu próprio ponteiro inteligente que notificará os referenciadores. Não é tão difícil assim.

Os ponteiros fracos não têm notificação porque exigiriam uma lista de referências fracas que existem e que, por sua vez, exigiriam sincronização não trivial no ambiente multiencadeado, enquanto a implementação sem ele exigiria apenas um nível extra de indireção. Mas especialmente se você tiver algumas restrições de quais encadeamentos os modelos podem ser excluídos (frameworks de GUI são normalmente single-threaded), é possível.

    
por 26.07.2013 / 11:07
fonte
0

Se eu entendi seu design corretamente, você tem um modelo de visualização de modelo.

Para melhorá-lo, você pode usar o design MVC com o observador padrão, onde:

  • os controladores estão apenas conectando modelos - > exibições e exibições - > modela os sinais para os slots
  • As visualizações
  • mostram o que precisam mostrar, ouvem eventos relevantes do modelo para atualizar a exibição e encaminham a interação do usuário para os modelos
  • Modelos
  • estão implementando a lógica. Eles lidam com a interação do usuário e enviam eventos para exibições para informar sobre alterações

Desta forma, se você deseja destruir um modelo, você pode fazê-lo sem muita pressa. Você também terá que quebrar as conexões no controlador.

Aqui você pode ver como eu implementei o MVC no qt5. Pode evoluir para algo útil no futuro distante, mas por enquanto é apenas para fins de demonstração:)

    
por 04.12.2013 / 09:24
fonte

Tags