Existe uma coleção de diretrizes de design comumente acordadas para separar as classes Model das classes View / Controller em um aplicativo Java Swing? Não estou tão preocupado com o fato de o View / Controller não saber nada sobre o modelo como o contrário: eu gostaria de projetar meu modelo para não ter conhecimento de nada no javax.swing. Idealmente, ele deve ter uma API simples, permitindo que ela seja impulsionada por algo tão primitivo quanto uma CLI. Deveria ser, de maneira geral, um "mecanismo".
A comunicação de eventos da GUI ao modelo não é muito difícil - os Action Performers podem chamar a API do modelo. Mas e quando o modelo faz suas próprias alterações de estado que precisam ser refletidas na GUI? É para isso que serve "ouvir", mas mesmo "ser ouvido" não é inteiramente passivo; requer que o modelo saiba sobre a adição de um ouvinte.
O problema específico que me fez pensar envolve uma fila de arquivos. No lado da GUI, há um DefaultListModel
por trás de JList
e há algumas coisas da GUI para escolher arquivos do sistema de arquivos e adicioná-los à JList. No lado do modelo, ele deseja extrair os arquivos da parte inferior dessa "fila" (fazendo com que eles desapareçam da JList) e processá-los de alguma maneira. De fato, o código do modelo já está gravado - atualmente mantém ArrayList<File>
e expõe um add(File)
método público . Mas não sei como fazer com que meu modelo funcione com o View / Controller sem algumas modificações pesadas e específicas do Swing no modelo.
Sou muito novo em programação Java e GUI, sempre tendo feito programação em "lote" e "back-end" até agora - daí o meu interesse em manter uma divisão estrita entre modelo e interface do usuário, se possível e possível ser ensinado.
Respostas:
Não há diretrizes de projeto comumente acordadas (ou seja, defacto ) para o MVC. Não é tão difícil fazê-lo você mesmo, mas exige algum planejamento em suas aulas e muito tempo e paciência.
A razão pela qual não existe uma solução definitiva é porque existem várias maneiras de fazer o MVC, todas com seus prós e contras. Portanto, seja esperto e faça o que melhor lhe convier.
Para responder sua pergunta, você também deseja desacoplar o controlador da visualização (para poder usar a mesma lógica de regra de negócios para um aplicativo Swing e no aplicativo do console). No exemplo do Swing, você deseja desacoplar o controlador do
JWindow
e de qualquer widget no Swing. O jeito que eu costumava fazer (antes de usar estruturas reais) é criar uma interface para a visualização que o controlador usa:Para esta solução durante a inicialização, você precisa registrar o controlador na visualização.
Pode ser uma boa ideia criar um contêiner de IoC para fazer toda a configuração para você.
De qualquer forma, dessa maneira, você pode implementar visualizações somente do console, usando os mesmos controladores:
A parte divertida é como lidar com eventos. Eu implementei isso permitindo que a visualização se registrasse no controlador usando uma interface, isso é feito usando o padrão Observer (se você estiver usando o .NET, você usaria manipuladores de eventos). Aqui está um exemplo de um "observador de documentos" simples, que sinaliza quando o documento foi salvo ou carregado.
Dessa forma, a exibição pode se atualizar adequadamente, pois está assinando as atualizações do documento. Tudo o que precisa fazer é implementar a
DocumentObserver
interface:Espero que esses exemplos motivadores lhe dê algumas idéias sobre como fazer você mesmo. No entanto, eu recomendo fortemente que você considere o uso de estruturas em Java que fazem a maioria das coisas para você; caso contrário, você acabará tendo muito código clichê que demora muito tempo para escrever. Existem algumas RCP (Rich Client Platforms) que você pode usar para implementar algumas das funcionalidades básicas que você provavelmente precisa, como manipulação de documentos em todo o aplicativo e muita manipulação de eventos básicos.
Há alguns que consigo pensar na minha cabeça: Eclipse e RCP do Netbeans .
Você ainda precisa desenvolver controladores e modelos para si mesmo, mas é por isso que você usa um ORM. O exemplo seria o Hibernate .
Os contêineres de IoC são legais, mas também existem estruturas para isso. Como o Spring (que também lida com dados, entre outras coisas).
fonte
Minha opinião é que, às vezes, precisamos comprometer
Como você disse, seria ótimo se pudéssemos propagar a notificação de alteração implicitamente sem que o objeto observado tivesse infraestrutura explícita para isso. Para linguagens imperativas comuns como Java, C #, C ++, sua arquitetura de tempo de execução é muito leve, a partir de agora, de qualquer maneira. Com isso, quero dizer que não faz parte da especificação de linguagem no momento.
No seu caso particular, não acho que seja exatamente ruim definir / usar alguma interface genérica como INotifyPropertyChanged (como em c #), pois isso não é acoplado automaticamente a uma exibição de qualquer maneira - apenas diz que, se eu mudar, Eu vou te contar .
Mais uma vez, concordo que seria ótimo se não tivéssemos que definir a notificação de alteração, mas, novamente, se estivesse implícita em todas as classes, poderia ocorrer uma sobrecarga.
fonte